summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2022-12-27 17:20:04 +0900
committerJinWang An <jinwang.an@samsung.com>2022-12-27 17:20:04 +0900
commitee94ded5e1f6585451d7376f711dc12cb3d92a01 (patch)
tree4f02ee3ee8746576052abd0ec3a746631dfa96e2
parente502e056ca86a2eea429e09cd2f5d9c14105ee90 (diff)
downloadcmake-ee94ded5e1f6585451d7376f711dc12cb3d92a01.tar.gz
cmake-ee94ded5e1f6585451d7376f711dc12cb3d92a01.tar.bz2
cmake-ee94ded5e1f6585451d7376f711dc12cb3d92a01.zip
Imported Upstream version 3.22.0upstream/3.22.0
-rw-r--r--Auxiliary/vim/syntax/cmake.vim2
-rw-r--r--CMakeLists.txt10
-rw-r--r--Help/command/cmake_host_system_information.rst268
-rw-r--r--Help/command/configure_file.rst1
-rw-r--r--Help/command/ctest_submit.rst3
-rw-r--r--Help/command/ctest_test.rst56
-rw-r--r--Help/command/file.rst26
-rw-r--r--Help/command/find_package.rst456
-rw-r--r--Help/command/get_property.rst2
-rw-r--r--Help/command/if.rst2
-rw-r--r--Help/command/install.rst4
-rw-r--r--Help/command/list.rst10
-rw-r--r--Help/command/set_property.rst4
-rw-r--r--Help/command/source_group.rst3
-rw-r--r--Help/command/string.rst91
-rw-r--r--Help/command/try_compile.rst8
-rw-r--r--Help/command/try_run.rst5
-rw-r--r--Help/cpack_gen/deb.rst30
-rw-r--r--Help/cpack_gen/nsis.rst10
-rw-r--r--Help/cpack_gen/rpm.rst19
-rw-r--r--Help/dev/documentation.rst5
-rw-r--r--Help/envvar/CMAKE_BUILD_TYPE.rst10
-rw-r--r--Help/envvar/CMAKE_CONFIGURATION_TYPES.rst11
-rw-r--r--Help/envvar/CMAKE_INSTALL_MODE.rst37
-rw-r--r--Help/generator/Visual Studio 10 2010.rst9
-rw-r--r--Help/generator/Visual Studio 15 2017.rst26
-rw-r--r--Help/guide/tutorial/A Basic Starting Point.rst70
-rw-r--r--Help/guide/tutorial/Adding Export Configuration.rst48
-rw-r--r--Help/guide/tutorial/Adding Generator Expressions.rst10
-rw-r--r--Help/guide/tutorial/Adding Support for a Testing Dashboard.rst20
-rw-r--r--Help/guide/tutorial/Adding System Introspection.rst5
-rw-r--r--Help/guide/tutorial/Adding a Library.rst9
-rw-r--r--Help/guide/tutorial/Complete/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Installing and Testing.rst8
-rw-r--r--Help/guide/tutorial/Step10/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step11/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step12/CMakeLists.txt6
-rw-r--r--Help/guide/tutorial/Step5/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step6/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step7/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step8/CMakeLists.txt4
-rw-r--r--Help/guide/tutorial/Step8/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step9/CMakeLists.txt4
-rw-r--r--Help/manual/cmake-buildsystem.7.rst153
-rw-r--r--Help/manual/cmake-compile-features.7.rst13
-rw-r--r--Help/manual/cmake-env-variables.7.rst3
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst4
-rw-r--r--Help/manual/cmake-packages.7.rst6
-rw-r--r--Help/manual/cmake-policies.7.rst9
-rw-r--r--Help/manual/cmake-properties.7.rst8
-rw-r--r--Help/manual/cmake-variables.7.rst16
-rw-r--r--Help/manual/ctest.1.rst4
-rw-r--r--Help/manual/presets/schema.json6
-rw-r--r--Help/policy/CMP0127.rst34
-rw-r--r--Help/policy/CMP0128.rst71
-rw-r--r--Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst2
-rw-r--r--Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst6
-rw-r--r--Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst14
-rw-r--r--Help/prop_sf/VS_SETTINGS.rst7
-rw-r--r--Help/prop_test/ENVIRONMENT.rst4
-rw-r--r--Help/prop_test/ENVIRONMENT_MODIFICATION.rst36
-rw-r--r--Help/prop_test/LABELS.rst8
-rw-r--r--Help/prop_tgt/AUTOMOC.rst15
-rw-r--r--Help/prop_tgt/AUTORCC.rst4
-rw-r--r--Help/prop_tgt/AUTOUIC.rst4
-rw-r--r--Help/prop_tgt/CUDA_EXTENSIONS.rst6
-rw-r--r--Help/prop_tgt/CUDA_STANDARD.rst16
-rw-r--r--Help/prop_tgt/CXX_EXTENSIONS.rst6
-rw-r--r--Help/prop_tgt/C_EXTENSIONS.rst6
-rw-r--r--Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst16
-rw-r--r--Help/prop_tgt/HIP_EXTENSIONS.rst21
-rw-r--r--Help/prop_tgt/HIP_STANDARD.rst48
-rw-r--r--Help/prop_tgt/HIP_STANDARD_REQUIRED.rst19
-rw-r--r--Help/prop_tgt/LANG_EXTENSIONS.rst24
-rw-r--r--Help/prop_tgt/LANG_STANDARD.rst26
-rw-r--r--Help/prop_tgt/LANG_STANDARD_REQUIRED.rst26
-rw-r--r--Help/prop_tgt/LINK_WHAT_YOU_USE.rst24
-rw-r--r--Help/prop_tgt/OBJCXX_EXTENSIONS.rst6
-rw-r--r--Help/prop_tgt/OBJC_EXTENSIONS.rst6
-rw-r--r--Help/release/3.21.rst7
-rw-r--r--Help/release/3.22.rst144
-rw-r--r--Help/release/index.rst1
-rw-r--r--Help/variable/CMAKE_BUILD_TYPE.rst36
-rw-r--r--Help/variable/CMAKE_CONFIGURATION_TYPES.rst22
-rw-r--r--Help/variable/CMAKE_CUDA_EXTENSIONS.rst7
-rw-r--r--Help/variable/CMAKE_CUDA_STANDARD.rst7
-rw-r--r--Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst7
-rw-r--r--Help/variable/CMAKE_CXX_EXTENSIONS.rst7
-rw-r--r--Help/variable/CMAKE_CXX_STANDARD.rst7
-rw-r--r--Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst7
-rw-r--r--Help/variable/CMAKE_C_EXTENSIONS.rst7
-rw-r--r--Help/variable/CMAKE_C_STANDARD.rst7
-rw-r--r--Help/variable/CMAKE_C_STANDARD_REQUIRED.rst7
-rw-r--r--Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst2
-rw-r--r--Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst7
-rw-r--r--Help/variable/CMAKE_HIP_EXTENSIONS.rst10
-rw-r--r--Help/variable/CMAKE_HIP_STANDARD.rst10
-rw-r--r--Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst10
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst18
-rw-r--r--Help/variable/CMAKE_LANG_EXTENSIONS.rst20
-rw-r--r--Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst10
-rw-r--r--Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst18
-rw-r--r--Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst20
-rw-r--r--Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst9
-rw-r--r--Help/variable/CMAKE_LANG_SIMULATE_ID.rst6
-rw-r--r--Help/variable/CMAKE_LANG_STANDARD.rst19
-rw-r--r--Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst7
-rw-r--r--Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst19
-rw-r--r--Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst2
-rw-r--r--Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst10
-rw-r--r--Help/variable/CMAKE_NETRC.rst10
-rw-r--r--Help/variable/CMAKE_NETRC_FILE.rst10
-rw-r--r--Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst7
-rw-r--r--Help/variable/CMAKE_OBJCXX_STANDARD.rst7
-rw-r--r--Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst7
-rw-r--r--Help/variable/CMAKE_OBJC_EXTENSIONS.rst7
-rw-r--r--Help/variable/CMAKE_OBJC_STANDARD.rst7
-rw-r--r--Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst7
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst7
-rw-r--r--Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst14
-rw-r--r--Help/variable/CMAKE_TLS_CAINFO.rst9
-rw-r--r--Help/variable/CMAKE_TLS_VERIFY.rst4
-rw-r--r--Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst13
-rw-r--r--Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst13
-rw-r--r--Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst17
-rw-r--r--Help/variable/MSVC_TOOLSET_VERSION.rst1
-rw-r--r--Modules/CMakeASM_MASMInformation.cmake2
-rw-r--r--Modules/CMakeASM_NASMInformation.cmake2
-rw-r--r--Modules/CMakeCCompiler.cmake.in10
-rw-r--r--Modules/CMakeCCompilerId.c.in32
-rw-r--r--Modules/CMakeCInformation.cmake10
-rw-r--r--Modules/CMakeCUDACompiler.cmake.in1
-rw-r--r--Modules/CMakeCUDACompilerId.cu.in15
-rw-r--r--Modules/CMakeCUDAInformation.cmake9
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in10
-rw-r--r--Modules/CMakeCXXCompilerId.cpp.in16
-rw-r--r--Modules/CMakeCXXInformation.cmake9
-rw-r--r--Modules/CMakeCheckCompilerFlagCommonPatterns.cmake1
-rw-r--r--Modules/CMakeDependentOption.cmake61
-rw-r--r--Modules/CMakeDetermineASMCompiler.cmake19
-rw-r--r--Modules/CMakeDetermineCCompiler.cmake5
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake24
-rw-r--r--Modules/CMakeDetermineCXXCompiler.cmake5
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake44
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake5
-rw-r--r--Modules/CMakeFindBinUtils.cmake15
-rw-r--r--Modules/CMakeFindPackageMode.cmake2
-rw-r--r--Modules/CMakeFortranCompiler.cmake.in9
-rw-r--r--Modules/CMakeFortranCompilerABI.F9048
-rw-r--r--Modules/CMakeFortranInformation.cmake9
-rw-r--r--Modules/CMakeHIPCompiler.cmake.in1
-rw-r--r--Modules/CMakeHIPCompilerId.hip.in13
-rw-r--r--Modules/CMakeHIPInformation.cmake9
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in1
-rw-r--r--Modules/CMakeOBJCCompilerId.m.in29
-rw-r--r--Modules/CMakeOBJCInformation.cmake9
-rw-r--r--Modules/CMakeOBJCXXCompiler.cmake.in1
-rw-r--r--Modules/CMakeOBJCXXCompilerId.mm.in13
-rw-r--r--Modules/CMakeOBJCXXInformation.cmake9
-rw-r--r--Modules/CMakeSwiftInformation.cmake9
-rw-r--r--Modules/CMakeTestFortranCompiler.cmake9
-rw-r--r--Modules/CMakeTestHIPCompiler.cmake2
-rw-r--r--Modules/CPackIFW.cmake1
-rw-r--r--Modules/CheckCXXSymbolExists.cmake2
-rw-r--r--Modules/CheckFortranFunctionExists.cmake6
-rw-r--r--Modules/CheckLanguage.cmake2
-rw-r--r--Modules/CheckLinkerFlag.cmake6
-rw-r--r--Modules/CheckSymbolExists.cmake2
-rw-r--r--Modules/Compiler/ARMClang-C.cmake8
-rw-r--r--Modules/Compiler/ARMClang-CXX.cmake8
-rw-r--r--Modules/Compiler/AppleClang-CXX.cmake10
-rw-r--r--Modules/Compiler/CMakeCommonCompilerMacros.cmake18
-rw-r--r--Modules/Compiler/Clang-C.cmake1
-rw-r--r--Modules/Compiler/Clang-CXX.cmake1
-rw-r--r--Modules/Compiler/IAR-ASM.cmake74
-rw-r--r--Modules/Compiler/IAR-C.cmake43
-rw-r--r--Modules/Compiler/IAR-CXX.cmake64
-rw-r--r--Modules/Compiler/IAR-DetermineCompiler.cmake42
-rw-r--r--Modules/Compiler/IAR.cmake60
-rw-r--r--Modules/Compiler/Intel-C.cmake1
-rw-r--r--Modules/Compiler/Intel-CXX.cmake1
-rw-r--r--Modules/Compiler/IntelLLVM-C.cmake1
-rw-r--r--Modules/Compiler/IntelLLVM-CXX.cmake1
-rw-r--r--Modules/Compiler/MSVC-C.cmake75
-rw-r--r--Modules/Compiler/MSVC-CXX.cmake7
-rw-r--r--Modules/Compiler/NVHPC.cmake1
-rw-r--r--Modules/Compiler/PGI.cmake2
-rw-r--r--Modules/CompilerId/VS-10.csproj.in3
-rw-r--r--Modules/ExternalProject.cmake8
-rw-r--r--Modules/FetchContent.cmake484
-rw-r--r--Modules/FindBLAS.cmake392
-rw-r--r--Modules/FindCUDAToolkit.cmake26
-rw-r--r--Modules/FindFLTK.cmake12
-rw-r--r--Modules/FindGLUT.cmake163
-rw-r--r--Modules/FindHDF5.cmake10
-rw-r--r--Modules/FindICU.cmake4
-rw-r--r--Modules/FindJasper.cmake95
-rw-r--r--Modules/FindLAPACK.cmake289
-rw-r--r--Modules/FindMPI.cmake90
-rw-r--r--Modules/FindMPI/test_mpi.c18
-rw-r--r--Modules/FindMatlab.cmake80
-rw-r--r--Modules/FindPatch.cmake2
-rw-r--r--Modules/FindPkgConfig.cmake85
-rw-r--r--Modules/FindThreads.cmake2
-rw-r--r--Modules/FindX11.cmake6
-rw-r--r--Modules/GNUInstallDirs.cmake37
-rw-r--r--Modules/GetPrerequisites.cmake2
-rw-r--r--Modules/GoogleTest.cmake17
-rw-r--r--Modules/GoogleTestAddTests.cmake11
-rw-r--r--Modules/InstallRequiredSystemLibraries.cmake37
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake6
-rw-r--r--Modules/Internal/CPack/CPackRPM.cmake12
-rw-r--r--Modules/Internal/CPack/NSIS.template.in17
-rw-r--r--Modules/Internal/OSRelease/010-TryOldCentOS.cmake41
-rw-r--r--Modules/Internal/OSRelease/020-TryDebianVersion.cmake38
-rw-r--r--Modules/Platform/Android-Determine.cmake4
-rw-r--r--Modules/Platform/Windows-Clang.cmake6
-rw-r--r--Modules/Platform/Windows-GNU.cmake44
-rw-r--r--Modules/Platform/Windows-Intel-C.cmake2
-rw-r--r--Modules/Platform/Windows-Intel-CXX.cmake2
-rw-r--r--Modules/Platform/Windows-IntelLLVM.cmake2
-rw-r--r--Modules/UseSWIG.cmake27
-rw-r--r--Modules/VTKCompatibility.cmake4
-rw-r--r--Source/CMakeLists.txt43
-rw-r--r--Source/CMakeVersion.cmake6
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx10
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.h4
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx57
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx111
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx96
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx25
-rw-r--r--Source/CPack/OSXScriptLauncher.cxx2
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx87
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx20
-rw-r--r--Source/CPack/cmCPackBundleGenerator.cxx48
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.cxx8
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx490
-rw-r--r--Source/CPack/cmCPackDebGenerator.h5
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx58
-rw-r--r--Source/CPack/cmCPackExternalGenerator.cxx37
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx4
-rw-r--r--Source/CPack/cmCPackGenerator.cxx231
-rw-r--r--Source/CPack/cmCPackGenerator.h19
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx77
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.cxx14
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx19
-rw-r--r--Source/CPack/cmCPackPKGGenerator.cxx14
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx31
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx19
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.h4
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx29
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx6
-rw-r--r--Source/CPack/cpack.cxx16
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx12
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx6
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx12
-rw-r--r--Source/CTest/cmCTestGIT.cxx1
-rw-r--r--Source/CTest/cmCTestGenericHandler.cxx30
-rw-r--r--Source/CTest/cmCTestGenericHandler.h13
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx6
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx2
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h4
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx5
-rw-r--r--Source/CTest/cmCTestRunTest.cxx194
-rw-r--r--Source/CTest/cmCTestRunTest.h3
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx10
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx12
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx18
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx27
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx30
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx239
-rw-r--r--Source/CTest/cmCTestTestHandler.h21
-rw-r--r--Source/CTest/cmCTestTestMeasurementXMLParser.cxx26
-rw-r--r--Source/CTest/cmCTestTestMeasurementXMLParser.h21
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx2
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx5
-rw-r--r--Source/CTest/cmCTestUpdateHandler.h2
-rw-r--r--Source/CTest/cmCTestVC.cxx2
-rw-r--r--Source/CursesDialog/cmCursesCacheEntryComposite.cxx6
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx20
-rw-r--r--Source/LexerParser/cmFortranParser.cxx78
-rw-r--r--Source/LexerParser/cmFortranParser.y4
-rw-r--r--Source/QtDialog/CMakeSetup.cxx14
-rw-r--r--Source/QtDialog/QCMake.cxx35
-rw-r--r--Source/cmAddLibraryCommand.cxx1
-rw-r--r--Source/cmAddTestCommand.cxx2
-rw-r--r--Source/cmAlgorithms.h12
-rw-r--r--Source/cmArchiveWrite.cxx3
-rw-r--r--Source/cmBinUtilsLinuxELFLinker.cxx11
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.cxx42
-rw-r--r--Source/cmBinUtilsMacOSMachOLinker.h10
-rw-r--r--Source/cmBuildCommand.cxx4
-rw-r--r--Source/cmBuildNameCommand.cxx4
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx613
-rw-r--r--Source/cmCMakePathCommand.cxx4
-rw-r--r--Source/cmCMakePolicyCommand.cxx1
-rw-r--r--Source/cmCPluginAPI.cxx8
-rw-r--r--Source/cmCTest.cxx16
-rw-r--r--Source/cmCacheManager.cxx38
-rw-r--r--Source/cmCacheManager.h30
-rw-r--r--Source/cmCommand.h2
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx9
-rw-r--r--Source/cmCommonTargetGenerator.cxx29
-rw-r--r--Source/cmCommonTargetGenerator.h6
-rw-r--r--Source/cmComputeLinkDepends.cxx8
-rw-r--r--Source/cmComputeLinkInformation.cxx50
-rw-r--r--Source/cmComputeLinkInformation.h3
-rw-r--r--Source/cmComputeTargetDepends.cxx9
-rw-r--r--Source/cmConditionEvaluator.cxx988
-rw-r--r--Source/cmConditionEvaluator.h36
-rw-r--r--Source/cmConfigure.cmake.h.in1
-rw-r--r--Source/cmCoreTryCompile.cxx43
-rw-r--r--Source/cmCurl.cxx48
-rw-r--r--Source/cmCurl.h3
-rw-r--r--Source/cmCustomCommandGenerator.cxx16
-rw-r--r--Source/cmDefinitions.cxx6
-rw-r--r--Source/cmDefinitions.h4
-rw-r--r--Source/cmDepends.cxx4
-rw-r--r--Source/cmDependsC.cxx6
-rw-r--r--Source/cmDependsFortran.cxx21
-rw-r--r--Source/cmDependsFortran.h3
-rw-r--r--Source/cmELF.cxx74
-rw-r--r--Source/cmELF.h7
-rw-r--r--Source/cmExportBuildFileGenerator.cxx7
-rw-r--r--Source/cmExportBuildFileGenerator.h8
-rw-r--r--Source/cmExportCommand.cxx1
-rw-r--r--Source/cmExportFileGenerator.cxx82
-rw-r--r--Source/cmExportFileGenerator.h37
-rw-r--r--Source/cmExportInstallFileGenerator.cxx15
-rw-r--r--Source/cmExportInstallFileGenerator.h8
-rw-r--r--Source/cmExportLibraryDependenciesCommand.cxx4
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx6
-rw-r--r--Source/cmExportTryCompileFileGenerator.h5
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx10
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx9
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx16
-rw-r--r--Source/cmExtraKateGenerator.cxx4
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx14
-rw-r--r--Source/cmFileAPICache.cxx4
-rw-r--r--Source/cmFileAPICodemodel.cxx19
-rw-r--r--Source/cmFileAPIToolchains.cxx4
-rw-r--r--Source/cmFileCommand.cxx83
-rw-r--r--Source/cmFileCopier.cxx4
-rw-r--r--Source/cmFileCopier.h5
-rw-r--r--Source/cmFileInstaller.cxx119
-rw-r--r--Source/cmFileInstaller.h5
-rw-r--r--Source/cmFindBase.cxx14
-rw-r--r--Source/cmFindCommon.cxx14
-rw-r--r--Source/cmFindLibraryCommand.cxx43
-rw-r--r--Source/cmFindPackageCommand.cxx46
-rw-r--r--Source/cmForEachCommand.cxx1
-rw-r--r--Source/cmFortranParser.h5
-rw-r--r--Source/cmFortranParserImpl.cxx13
-rw-r--r--Source/cmGeneratorExpressionNode.cxx27
-rw-r--r--Source/cmGeneratorTarget.cxx500
-rw-r--r--Source/cmGeneratorTarget.h59
-rw-r--r--Source/cmGetCMakePropertyCommand.cxx8
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx13
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx4
-rw-r--r--Source/cmGetPropertyCommand.cxx40
-rw-r--r--Source/cmGetSourceFilePropertyCommand.cxx4
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx6
-rw-r--r--Source/cmGetTestPropertyCommand.cxx5
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx12
-rw-r--r--Source/cmGlobalCommonGenerator.cxx39
-rw-r--r--Source/cmGlobalCommonGenerator.h5
-rw-r--r--Source/cmGlobalGenerator.cxx127
-rw-r--r--Source/cmGlobalGenerator.h22
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx29
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx5
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h2
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx6
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h2
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx126
-rw-r--r--Source/cmGlobalNinjaGenerator.h6
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx34
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx16
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h6
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx12
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx54
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h3
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx60
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h10
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx4
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h7
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx33
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.h5
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx86
-rw-r--r--Source/cmGlobalXCodeGenerator.h7
-rw-r--r--Source/cmGraphVizWriter.cxx6
-rw-r--r--Source/cmIncludeCommand.cxx1
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx1
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx5
-rw-r--r--Source/cmIncludeGuardCommand.cxx1
-rw-r--r--Source/cmIncludeRegularExpressionCommand.cxx2
-rw-r--r--Source/cmInstallCommand.cxx11
-rw-r--r--Source/cmInstallMode.h17
-rw-r--r--Source/cmInstallSubdirectoryGenerator.cxx1
-rw-r--r--Source/cmInstallTargetGenerator.cxx71
-rw-r--r--Source/cmInstalledFile.cxx1
-rw-r--r--Source/cmLinkDirectoriesCommand.cxx2
-rw-r--r--Source/cmLinkItem.cxx12
-rw-r--r--Source/cmLinkLineDeviceComputer.cxx4
-rw-r--r--Source/cmListCommand.cxx6
-rw-r--r--Source/cmListFileCache.cxx4
-rw-r--r--Source/cmLocalCommonGenerator.cxx4
-rw-r--r--Source/cmLocalGenerator.cxx316
-rw-r--r--Source/cmLocalGenerator.h24
-rw-r--r--Source/cmLocalNinjaGenerator.cxx13
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx30
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx49
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx16
-rw-r--r--Source/cmLocalVisualStudioGenerator.h6
-rw-r--r--Source/cmMakefile.cxx240
-rw-r--r--Source/cmMakefile.h48
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx39
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx35
-rw-r--r--Source/cmMakefileProfilingData.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx121
-rw-r--r--Source/cmMarkAsAdvancedCommand.cxx1
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx67
-rw-r--r--Source/cmNinjaTargetGenerator.cxx89
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx4
-rw-r--r--Source/cmOptionCommand.cxx10
-rw-r--r--Source/cmOutputConverter.cxx3
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx4
-rw-r--r--Source/cmParseArgumentsCommand.cxx4
-rw-r--r--Source/cmPolicies.cxx1
-rw-r--r--Source/cmPolicies.h8
-rw-r--r--Source/cmProjectCommand.cxx6
-rw-r--r--Source/cmProperty.h14
-rw-r--r--Source/cmPropertyMap.cxx13
-rw-r--r--Source/cmPropertyMap.h9
-rw-r--r--Source/cmQTWrapCPPCommand.cxx3
-rw-r--r--Source/cmQtAutoGen.cxx13
-rw-r--r--Source/cmQtAutoGen.h4
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx6
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.h2
-rw-r--r--Source/cmQtAutoGenInitializer.cxx15
-rw-r--r--Source/cmQtAutoGenInitializer.h16
-rw-r--r--Source/cmQtAutoGenerator.cxx1
-rw-r--r--Source/cmQtAutoMocUic.cxx6
-rw-r--r--Source/cmRST.cxx5
-rw-r--r--Source/cmRST.h1
-rw-r--r--Source/cmRemoveCommand.cxx4
-rw-r--r--Source/cmRuntimeDependencyArchive.cxx1
-rw-r--r--Source/cmSearchPath.cxx8
-rw-r--r--Source/cmSeparateArgumentsCommand.cxx7
-rw-r--r--Source/cmSetCommand.cxx4
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.cxx2
-rw-r--r--Source/cmSetPropertyCommand.cxx15
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx2
-rw-r--r--Source/cmSetTestsPropertiesCommand.cxx2
-rw-r--r--Source/cmSiteNameCommand.cxx7
-rw-r--r--Source/cmSourceFile.cxx39
-rw-r--r--Source/cmSourceFile.h14
-rw-r--r--Source/cmStandardLevelResolver.cxx150
-rw-r--r--Source/cmStandardLevelResolver.h8
-rw-r--r--Source/cmState.cxx78
-rw-r--r--Source/cmState.h52
-rw-r--r--Source/cmStateDirectory.cxx240
-rw-r--r--Source/cmStateDirectory.h63
-rw-r--r--Source/cmStatePrivate.h15
-rw-r--r--Source/cmStateSnapshot.cxx36
-rw-r--r--Source/cmStateSnapshot.h3
-rw-r--r--Source/cmStringAlgorithms.cxx79
-rw-r--r--Source/cmStringAlgorithms.h102
-rw-r--r--Source/cmStringCommand.cxx6
-rw-r--r--Source/cmSystemTools.cxx246
-rw-r--r--Source/cmSystemTools.h11
-rw-r--r--Source/cmTarget.cxx443
-rw-r--r--Source/cmTarget.h66
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx3
-rw-r--r--Source/cmTargetExport.h1
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx2
-rw-r--r--Source/cmTargetLinkDirectoriesCommand.cxx3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx8
-rw-r--r--Source/cmTargetLinkOptionsCommand.cxx2
-rw-r--r--Source/cmTargetPropCommandBase.cxx4
-rw-r--r--Source/cmTargetPropertyComputer.cxx2
-rw-r--r--Source/cmTargetPropertyComputer.h26
-rw-r--r--Source/cmTest.cxx16
-rw-r--r--Source/cmTest.h8
-rw-r--r--Source/cmTestGenerator.cxx4
-rw-r--r--Source/cmTimestamp.cxx29
-rw-r--r--Source/cmTryRunCommand.cxx8
-rw-r--r--Source/cmUVHandlePtr.h2
-rw-r--r--Source/cmUtilitySourceCommand.cxx6
-rw-r--r--Source/cmValue.cxx123
-rw-r--r--Source/cmValue.h314
-rw-r--r--Source/cmVariableRequiresCommand.cxx4
-rw-r--r--Source/cmVariableWatchCommand.cxx4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx358
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h14
-rw-r--r--Source/cmWhileCommand.cxx89
-rw-r--r--Source/cmWorkerPool.h4
-rw-r--r--Source/cmXCodeScheme.cxx8
-rw-r--r--Source/cmake.cxx140
-rw-r--r--Source/cmake.h27
-rw-r--r--Source/cmakemain.cxx10
-rw-r--r--Source/cmcmd.cxx14
-rw-r--r--Source/kwsys/Status.hxx.in5
-rw-r--r--Source/kwsys/SystemInformation.cxx6
-rw-r--r--Source/kwsys/SystemTools.cxx24
-rw-r--r--Source/kwsys/testDirectory.cxx2
-rw-r--r--Source/kwsys/testStatus.cxx12
-rw-r--r--Source/kwsys/testSystemTools.cxx2
-rw-r--r--Templates/MSBuild/FlagTables/v143_Link.json7
-rw-r--r--Tests/CMakeLib/testRST.expect6
-rw-r--r--Tests/CMakeLib/testRST.rst6
-rw-r--r--Tests/CMakeLib/testUVRAII.cxx6
-rw-r--r--Tests/CMakeLists.txt77
-rw-r--r--Tests/CMakeTests/CMakeLists.txt1
-rw-r--r--Tests/CPackNSISGenerator/CMakeLists.txt1
-rw-r--r--Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake9
-rw-r--r--Tests/CTestTestSerialInDepends/test.ctest3
-rw-r--r--Tests/Cuda/CMakeLists.txt1
-rw-r--r--Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt16
-rw-r--r--Tests/Cuda/ConsumeCompileFeatures/main.cu20
-rw-r--r--Tests/Cuda/ConsumeCompileFeatures/static.cpp10
-rw-r--r--Tests/Cuda/ConsumeCompileFeatures/static.cu9
-rw-r--r--Tests/EnforceConfig.cmake.in1
-rw-r--r--Tests/Environment/CMakeLists.txt77
-rw-r--r--Tests/Environment/check_mod.cmake79
-rw-r--r--Tests/FindBLAS/CMakeLists.txt51
-rw-r--r--Tests/FindBLAS/Test/CMakeLists.txt11
-rw-r--r--Tests/FindBLAS/Test/main.c17
-rw-r--r--Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake53
-rw-r--r--Tests/FindGLUT/CMakeLists.txt9
-rw-r--r--Tests/FindGLUT/Test/CMakeLists.txt17
-rw-r--r--Tests/FindGLUT/Test/main.c11
-rw-r--r--Tests/FindJasper/CMakeLists.txt10
-rw-r--r--Tests/FindJasper/Test/CMakeLists.txt16
-rw-r--r--Tests/FindJasper/Test/main.c17
-rw-r--r--Tests/FindLAPACK/CMakeLists.txt51
-rw-r--r--Tests/FindLAPACK/Test/CMakeLists.txt11
-rw-r--r--Tests/FindLAPACK/Test/main.c20
-rw-r--r--Tests/FindMatlab/targets_checks/CMakeLists.txt44
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt25
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt26
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp3
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp2
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h2
-rw-r--r--Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt4
-rw-r--r--Tests/InstallMode/CMakeLists.txt124
-rw-r--r--Tests/InstallMode/README.txt43
-rw-r--r--Tests/InstallMode/Subproject.cmake73
-rw-r--r--Tests/InstallMode/Test.cmake38
-rw-r--r--Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt60
-rw-r--r--Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in8
-rw-r--r--Tests/InstallMode/subpro_a_static_lib/include/static_lib.h3
-rw-r--r--Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp10
-rw-r--r--Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt75
-rw-r--r--Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in8
-rw-r--r--Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h5
-rw-r--r--Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp10
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt10
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt61
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in8
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h3
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp10
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt71
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in11
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h3
-rw-r--r--Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp12
-rw-r--r--Tests/InstallMode/subpro_d_executable/CMakeLists.txt27
-rw-r--r--Tests/InstallMode/subpro_d_executable/src/main.cpp13
-rw-r--r--Tests/InstallMode/superpro/CMakeLists.txt29
-rw-r--r--Tests/InstallMode/superpro/file_copy.txt1
-rw-r--r--Tests/InstallMode/superpro/file_copy_file.txt1
-rw-r--r--Tests/InstallMode/superpro/file_create_link_symbolic.txt2
-rw-r--r--Tests/InstallMode/superpro/file_install.txt6
-rw-r--r--Tests/MSManifest/Subdir/CMakeLists.txt4
-rw-r--r--Tests/MSManifest/Subdir2/CMakeLists.txt2
-rw-r--r--Tests/Qt6Autogen/CMakeLists.txt8
-rw-r--r--Tests/QtAutogen/AutogenCoreTest.cmake16
-rw-r--r--Tests/QtAutogen/AutogenGuiTest.cmake16
-rw-r--r--Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Complex/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/Complex/codeeditor.cpp4
-rw-r--r--Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/MacOsFW/CMakeLists.txt22
-rw-r--r--Tests/QtAutogen/MacOsFW/src/CMakeLists.txt6
-rw-r--r--Tests/QtAutogen/MacOsFW/test/CMakeLists.txt12
-rw-r--r--Tests/QtAutogen/ManySources/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocCMP0071/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt1
-rw-r--r--Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt1
-rw-r--r--Tests/QtAutogen/MocCMP0100/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt1
-rw-r--r--Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt1
-rw-r--r--Tests/QtAutogen/MocInclude/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/MocMacroName/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocOnly/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocOptions/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/MocOsMacros/CMakeLists.txt6
-rw-r--r--Tests/QtAutogen/MocSkipSource/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/ObjectLibrary/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Parallel/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Parallel1/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Parallel2/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Parallel3/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/Parallel4/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/ParallelAUTO/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RccEmpty/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt8
-rw-r--r--Tests/QtAutogen/RccOnly/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RccSkipSource/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RerunMocBasic/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in2
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt9
-rw-r--r--Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RerunRccDepends/CMakeLists.txt3
-rw-r--r--Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt1
-rw-r--r--Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in2
-rw-r--r--Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/TestMacros.cmake11
-rw-r--r--Tests/QtAutogen/UicInclude/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/UicInterface/CMakeLists.txt6
-rw-r--r--Tests/QtAutogen/UicNoGui/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/UicOnly/CMakeLists.txt2
-rw-r--r--Tests/QtAutogen/UicSkipSource/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake2
-rw-r--r--Tests/RunCMake/Autogen/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Autogen/QtInFunction.cmake6
-rw-r--r--Tests/RunCMake/Autogen/QtInFunctionNested.cmake6
-rw-r--r--Tests/RunCMake/Autogen/QtInFunctionProperty.cmake6
-rw-r--r--Tests/RunCMake/Autogen/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt1
-rw-r--r--Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake2
-rw-r--r--Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake8
-rwxr-xr-xTests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt (renamed from Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt)0
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake9
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt9
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake9
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake7
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake (renamed from Tests/RunCMake/CMakeDependentOption/Regex.cmake)2
-rw-r--r--Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake6
-rw-r--r--Tests/RunCMake/CMakeLists.txt75
-rw-r--r--Tests/RunCMake/CPack/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake66
-rw-r--r--Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt4
-rw-r--r--Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake2
-rw-r--r--Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake3
-rw-r--r--Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake0
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt5
-rw-r--r--Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake0
-rw-r--r--Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/EnvBuildType.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/EnvConfigTypes.cmake2
-rw-r--r--Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt2
-rw-r--r--Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake1
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake30
-rw-r--r--Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt8
-rw-r--r--Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake7
-rw-r--r--Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt8
-rw-r--r--Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake6
-rw-r--r--Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake12
-rw-r--r--Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake9
-rw-r--r--Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake12
-rw-r--r--Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake8
-rw-r--r--Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake8
-rw-r--r--Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake9
-rw-r--r--Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake141
-rw-r--r--Tests/RunCMake/CompileFeatures/compiler_introspection.cmake38
-rw-r--r--Tests/RunCMake/CompileFeatures/empty.c2
-rw-r--r--Tests/RunCMake/CompileFeatures/generate_feature_list.cmake43
-rw-r--r--Tests/RunCMake/FetchContent/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/FetchContent/VarPassthroughs.cmake38
-rw-r--r--Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake17
-rw-r--r--Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt3
-rw-r--r--Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake29
-rw-r--r--Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake5
-rwxr-xr-xTests/RunCMake/FindPkgConfig/dummy-pkg-config.bat17
-rwxr-xr-xTests/RunCMake/FindPkgConfig/dummy-pkg-config.sh19
-rw-r--r--Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt7
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt5
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt (renamed from Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt)6
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt16
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt9
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTest.cmake18
-rw-r--r--Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake14
-rw-r--r--Tests/RunCMake/GoogleTest/RunCMakeTest.cmake65
-rw-r--r--Tests/RunCMake/GoogleTest/fake_gtest.cpp55
-rw-r--r--Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake21
-rw-r--r--Tests/RunCMake/Ninja/QtAutoMocDeps.cmake27
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/Ninja/RunCMakeTest.cmake21
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt2
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake10
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/QtX-automoc-check-ninja-stdout.txt (renamed from Tests/RunCMake/NinjaMultiConfig/Qt5-automoc-check-ninja-stdout.txt)0
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake (renamed from Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake)0
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/QtX.cmake (renamed from Tests/RunCMake/NinjaMultiConfig/Qt5.cmake)9
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake30
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake16
-rw-r--r--Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake24
-rw-r--r--Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/PrecompileHeaders/pch-included.c8
-rw-r--r--Tests/RunCMake/PrecompileHeaders/pch-included.cpp8
-rw-r--r--Tests/RunCMake/PrecompileHeaders/pch.h2
-rw-r--r--Tests/RunCMake/RunCMake.cmake3
-rw-r--r--Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/VS10Project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting-check.cmake40
-rw-r--r--Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting.cmake7
-rw-r--r--Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt2
-rw-r--r--Tests/RunCMake/VS10Project/VsSettings-check.cmake15
-rw-r--r--Tests/RunCMake/VS10Project/VsSettings.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake4
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake (renamed from Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake)2
-rw-r--r--Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake36
-rw-r--r--Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake21
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg1.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg2.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/BadArg3.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake)0
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt9
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo.cmake11
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt27
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in)24
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/QueryList.cmake (renamed from Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake)2
-rw-r--r--Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake23
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt14
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake11
-rw-r--r--Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release12
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest.cmake5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release9
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt5
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt7
-rw-r--r--Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake12
-rw-r--r--Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt1
-rw-r--r--Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt4
-rw-r--r--Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake1
-rw-r--r--Tests/RunCMake/ctest_environment/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake6
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake6
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake6
-rw-r--r--Tests/RunCMake/ctest_environment/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/ctest_environment/test.cmake.in16
-rw-r--r--Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake10
-rw-r--r--Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt2
-rw-r--r--Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake13
-rw-r--r--Tests/RunCMake/ctest_test/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake25
-rw-r--r--Tests/RunCMake/ctest_test/TestMeasurements-check.cmake18
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt4
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt4
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt4
-rw-r--r--Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt4
-rw-r--r--Tests/RunCMake/file-RPATH/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt4
-rw-r--r--Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt4
-rw-r--r--Tests/RunCMake/find_library/FromScriptMode-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/FromScriptMode.cmake15
-rw-r--r--Tests/RunCMake/find_library/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt1
-rw-r--r--Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt20
-rw-r--r--Tests/RunCMake/find_package/MissingNormalForceRequired.cmake3
-rw-r--r--Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt1
-rw-r--r--Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt11
-rw-r--r--Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake5
-rw-r--r--Tests/RunCMake/find_package/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/if/IncompleteMatches-stdout.txt6
-rw-r--r--Tests/RunCMake/if/IncompleteMatches.cmake36
-rw-r--r--Tests/RunCMake/if/IncompleteMatchesFail-result.txt1
-rw-r--r--Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt6
-rw-r--r--Tests/RunCMake/if/IncompleteMatchesFail.cmake2
-rw-r--r--Tests/RunCMake/if/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/if/unbalanced-parenthesis-result.txt1
-rw-r--r--Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt8
-rw-r--r--Tests/RunCMake/if/unbalanced-parenthesis.cmake8
-rw-r--r--Tests/RunCMake/install/CMP0087-OLD-stderr.txt8
-rw-r--r--Tests/RunCMake/string/Timestamp-stderr.txt2
-rw-r--r--Tests/RunCMake/string/Timestamp.cmake2
-rw-r--r--Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt6
-rw-r--r--Tests/RunCMake/while/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/while/unbalanced-parenthesis-result.txt1
-rw-r--r--Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt8
-rw-r--r--Tests/RunCMake/while/unbalanced-parenthesis.cmake8
-rw-r--r--Tests/UseSWIG/CMakeLists.txt3
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/IWYU/mapping.imp1
-rw-r--r--Utilities/KWIML/include/kwiml/int.h17
-rw-r--r--Utilities/Release/win/x86/Dockerfile4
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-elf.bash28
-rwxr-xr-xUtilities/Scripts/update-jsoncpp.bash2
-rwxr-xr-xUtilities/Scripts/update-libarchive.bash2
-rw-r--r--Utilities/Scripts/update-third-party.bash42
-rwxr-xr-xUtilities/Scripts/update-zstd.bash4
-rw-r--r--Utilities/Sphinx/CMakeLists.txt9
-rw-r--r--Utilities/cmThirdPartyChecks.cmake1
-rw-r--r--Utilities/cmcurl/CMake/CurlTests.c75
-rw-r--r--Utilities/cmcurl/CMake/OtherTests.cmake170
-rw-r--r--Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake14
-rw-r--r--Utilities/cmcurl/CMakeLists.txt193
-rw-r--r--Utilities/cmcurl/include/curl/curl.h19
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h8
-rw-r--r--Utilities/cmcurl/include/curl/urlapi.h3
-rw-r--r--Utilities/cmcurl/lib/altsvc.c12
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c185
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c1
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c257
-rw-r--r--Utilities/cmcurl/lib/c-hyper.h1
-rw-r--r--Utilities/cmcurl/lib/conncache.c12
-rw-r--r--Utilities/cmcurl/lib/connect.c84
-rw-r--r--Utilities/cmcurl/lib/cookie.c87
-rw-r--r--Utilities/cmcurl/lib/cookie.h1
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c6
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake139
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c42
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c4
-rw-r--r--Utilities/cmcurl/lib/curl_multibyte.c50
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c16
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c9
-rw-r--r--Utilities/cmcurl/lib/curl_range.c8
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c10
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h91
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h20
-rw-r--r--Utilities/cmcurl/lib/dict.c4
-rw-r--r--Utilities/cmcurl/lib/doh.c50
-rw-r--r--Utilities/cmcurl/lib/doh.h2
-rw-r--r--Utilities/cmcurl/lib/easy.c21
-rw-r--r--Utilities/cmcurl/lib/formdata.c16
-rw-r--r--Utilities/cmcurl/lib/ftp.c121
-rw-r--r--Utilities/cmcurl/lib/hostasyn.c1
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c12
-rw-r--r--Utilities/cmcurl/lib/hostip.c185
-rw-r--r--Utilities/cmcurl/lib/hostip.h4
-rw-r--r--Utilities/cmcurl/lib/hostip4.c3
-rw-r--r--Utilities/cmcurl/lib/hostip6.c31
-rw-r--r--Utilities/cmcurl/lib/hostsyn.c3
-rw-r--r--Utilities/cmcurl/lib/hsts.c51
-rw-r--r--Utilities/cmcurl/lib/hsts.h2
-rw-r--r--Utilities/cmcurl/lib/http.c281
-rw-r--r--Utilities/cmcurl/lib/http.h3
-rw-r--r--Utilities/cmcurl/lib/http2.c191
-rw-r--r--Utilities/cmcurl/lib/http2.h5
-rw-r--r--Utilities/cmcurl/lib/http_aws_sigv4.c12
-rw-r--r--Utilities/cmcurl/lib/http_digest.c3
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c6
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c6
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c130
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h7
-rw-r--r--Utilities/cmcurl/lib/imap.c55
-rw-r--r--Utilities/cmcurl/lib/inet_ntop.c2
-rw-r--r--Utilities/cmcurl/lib/krb5.c23
-rw-r--r--Utilities/cmcurl/lib/ldap.c20
-rw-r--r--Utilities/cmcurl/lib/md4.c6
-rw-r--r--Utilities/cmcurl/lib/md5.c9
-rw-r--r--Utilities/cmcurl/lib/mprintf.c4
-rw-r--r--Utilities/cmcurl/lib/mqtt.c258
-rw-r--r--Utilities/cmcurl/lib/multi.c162
-rw-r--r--Utilities/cmcurl/lib/multihandle.h3
-rw-r--r--Utilities/cmcurl/lib/netrc.c25
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c16
-rw-r--r--Utilities/cmcurl/lib/openldap.c9
-rw-r--r--Utilities/cmcurl/lib/pingpong.c4
-rw-r--r--Utilities/cmcurl/lib/pop3.c57
-rw-r--r--Utilities/cmcurl/lib/progress.c7
-rw-r--r--Utilities/cmcurl/lib/quic.h2
-rw-r--r--Utilities/cmcurl/lib/rand.c4
-rw-r--r--Utilities/cmcurl/lib/rtsp.c6
-rw-r--r--Utilities/cmcurl/lib/rtsp.h2
-rw-r--r--Utilities/cmcurl/lib/select.h20
-rw-r--r--Utilities/cmcurl/lib/sendf.c26
-rw-r--r--Utilities/cmcurl/lib/setopt.c14
-rw-r--r--Utilities/cmcurl/lib/sha256.c17
-rw-r--r--Utilities/cmcurl/lib/smb.c6
-rw-r--r--Utilities/cmcurl/lib/smtp.c22
-rw-r--r--Utilities/cmcurl/lib/socketpair.c36
-rw-r--r--Utilities/cmcurl/lib/socks.c72
-rw-r--r--Utilities/cmcurl/lib/socks_gssapi.c6
-rw-r--r--Utilities/cmcurl/lib/socks_sspi.c6
-rw-r--r--Utilities/cmcurl/lib/strdup.c28
-rw-r--r--Utilities/cmcurl/lib/strdup.h5
-rw-r--r--Utilities/cmcurl/lib/strerror.c7
-rw-r--r--Utilities/cmcurl/lib/telnet.c33
-rw-r--r--Utilities/cmcurl/lib/tftp.c40
-rw-r--r--Utilities/cmcurl/lib/transfer.c68
-rw-r--r--Utilities/cmcurl/lib/url.c149
-rw-r--r--Utilities/cmcurl/lib/urlapi.c27
-rw-r--r--Utilities/cmcurl/lib/urldata.h26
-rw-r--r--Utilities/cmcurl/lib/vauth/digest_sspi.c12
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_gssapi.c84
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c82
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c8
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c7
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_gssapi.c5
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c5
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h1
-rw-r--r--Utilities/cmcurl/lib/version.c14
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c205
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.h8
-rw-r--r--Utilities/cmcurl/lib/vquic/quiche.c32
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh.c65
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c132
-rw-r--r--Utilities/cmcurl/lib/vssh/ssh.h2
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c42
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c142
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c39
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c129
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c202
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c27
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c18
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c92
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c228
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c66
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c808
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c202
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c65
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h7
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c73
-rw-r--r--Utilities/cmcurl/lib/warnless.c106
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c60
-rw-r--r--Utilities/cmcurl/lib/x509asn1.h5
-rw-r--r--Utilities/cmelf/elf32.h265
-rw-r--r--Utilities/cmelf/elf64.h269
-rw-r--r--Utilities/cmelf/elf_common.h1492
-rw-r--r--Utilities/cmjsoncpp/include/json/allocator.h141
-rw-r--r--Utilities/cmjsoncpp/include/json/assertions.h43
-rw-r--r--Utilities/cmjsoncpp/include/json/config.h214
-rw-r--r--Utilities/cmjsoncpp/include/json/forwards.h10
-rw-r--r--Utilities/cmjsoncpp/include/json/json.h5
-rw-r--r--Utilities/cmjsoncpp/include/json/json_features.h (renamed from Utilities/cmjsoncpp/include/json/features.h)14
-rw-r--r--Utilities/cmjsoncpp/include/json/reader.h390
-rw-r--r--Utilities/cmjsoncpp/include/json/value.h608
-rw-r--r--Utilities/cmjsoncpp/include/json/version.h26
-rw-r--r--Utilities/cmjsoncpp/include/json/writer.h251
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_reader.cpp949
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_tool.h55
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_value.cpp1060
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl39
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_writer.cpp822
-rw-r--r--Utilities/cmlibarchive/CMakeLists.txt30
-rw-r--r--Utilities/cmlibarchive/COPYING1
-rw-r--r--Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake4
-rw-r--r--Utilities/cmlibarchive/build/cmake/config.h.in4
-rw-r--r--Utilities/cmlibarchive/build/version2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive.h11
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_acl.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_check_magic.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cryptor.c23
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_cryptor_private.h9
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_digest.c534
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_digest_private.h4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.c85
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry.h15
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_private.h16
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_entry_stat.34
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_ppmd7.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read.c17
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c48
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c46
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_filter.312
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_open_filename.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_set_format.c9
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_by_code.c83
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c23
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_by_code.c15
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c137
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c14
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c13
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c18
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c20
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c135
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.c52
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_string.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_util.c6
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.c42
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c26
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c79
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c52
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c19
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open.337
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_fd.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_file.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_filename.c21
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_open_memory.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_private.h1
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c4
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c2
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c3
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c49
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c7
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c5
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_set_options.33
-rw-r--r--Utilities/cmlibarchive/libarchive/config_freebsd.h2
-rw-r--r--Utilities/cmlibarchive/libarchive/cpio.52
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork.h9
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork_posix.c10
-rw-r--r--Utilities/cmlibarchive/libarchive/filter_fork_windows.c17
-rw-r--r--Utilities/cmlibuv/include/uv/win.h7
-rw-r--r--Utilities/cmlibuv/src/unix/core.c7
-rw-r--r--Utilities/cmlibuv/src/win/process.c5
-rw-r--r--Utilities/cmzstd/README.md12
-rw-r--r--Utilities/cmzstd/lib/common/bitstream.h41
-rw-r--r--Utilities/cmzstd/lib/common/compiler.h124
-rw-r--r--Utilities/cmzstd/lib/common/cpu.h4
-rw-r--r--Utilities/cmzstd/lib/common/debug.c2
-rw-r--r--Utilities/cmzstd/lib/common/debug.h31
-rw-r--r--Utilities/cmzstd/lib/common/entropy_common.c232
-rw-r--r--Utilities/cmzstd/lib/common/error_private.c3
-rw-r--r--Utilities/cmzstd/lib/common/error_private.h6
-rw-r--r--Utilities/cmzstd/lib/common/fse.h52
-rw-r--r--Utilities/cmzstd/lib/common/fse_decompress.c161
-rw-r--r--Utilities/cmzstd/lib/common/huf.h36
-rw-r--r--Utilities/cmzstd/lib/common/mem.h163
-rw-r--r--Utilities/cmzstd/lib/common/pool.c40
-rw-r--r--Utilities/cmzstd/lib/common/pool.h4
-rw-r--r--Utilities/cmzstd/lib/common/threading.c11
-rw-r--r--Utilities/cmzstd/lib/common/xxhash.c76
-rw-r--r--Utilities/cmzstd/lib/common/xxhash.h4
-rw-r--r--Utilities/cmzstd/lib/common/zstd_common.c20
-rw-r--r--Utilities/cmzstd/lib/common/zstd_deps.h111
-rw-r--r--Utilities/cmzstd/lib/common/zstd_internal.h167
-rw-r--r--Utilities/cmzstd/lib/common/zstd_trace.h154
-rw-r--r--Utilities/cmzstd/lib/compress/fse_compress.c55
-rw-r--r--Utilities/cmzstd/lib/compress/hist.c56
-rw-r--r--Utilities/cmzstd/lib/compress/hist.h4
-rw-r--r--Utilities/cmzstd/lib/compress/huf_compress.c391
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress.c3525
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_internal.h368
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_literals.c16
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_literals.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_sequences.c36
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_sequences.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_superblock.c317
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_compress_superblock.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_cwksp.h271
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_double_fast.c50
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_double_fast.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_fast.c46
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_fast.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_lazy.c1229
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_lazy.h60
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_ldm.c525
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_ldm.h11
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_ldm_geartab.h103
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_opt.c237
-rw-r--r--Utilities/cmzstd/lib/compress/zstd_opt.h2
-rw-r--r--Utilities/cmzstd/lib/compress/zstdmt_compress.c508
-rw-r--r--Utilities/cmzstd/lib/compress/zstdmt_compress.h144
-rw-r--r--Utilities/cmzstd/lib/decompress/huf_decompress.c581
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_ddict.c18
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_ddict.h4
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_decompress.c456
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_decompress_block.c266
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_decompress_block.h9
-rw-r--r--Utilities/cmzstd/lib/decompress/zstd_decompress_internal.h38
-rw-r--r--Utilities/cmzstd/lib/deprecated/zbuff.h2
-rw-r--r--Utilities/cmzstd/lib/deprecated/zbuff_common.c2
-rw-r--r--Utilities/cmzstd/lib/deprecated/zbuff_compress.c2
-rw-r--r--Utilities/cmzstd/lib/deprecated/zbuff_decompress.c2
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/cover.c82
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/cover.h13
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/divsufsort.c2
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/fastcover.c62
-rw-r--r--Utilities/cmzstd/lib/dictBuilder/zdict.c59
-rw-r--r--Utilities/cmzstd/lib/zdict.h (renamed from Utilities/cmzstd/lib/dictBuilder/zdict.h)157
-rw-r--r--Utilities/cmzstd/lib/zstd.h694
-rw-r--r--Utilities/cmzstd/lib/zstd_errors.h (renamed from Utilities/cmzstd/lib/common/zstd_errors.h)3
-rwxr-xr-xbootstrap2
1136 files changed, 31399 insertions, 16265 deletions
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index d2a04fec2..7a3e4ed62 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -160,6 +160,7 @@ syn keyword cmakeProperty contained
\ ENABLED_LANGUAGES
\ ENABLE_EXPORTS
\ ENVIRONMENT
+ \ ENVIRONMENT_MODIFICATION
\ EXCLUDE_FROM_ALL
\ EXCLUDE_FROM_DEFAULT_BUILD
\ EXPORT_NAME
@@ -2807,6 +2808,7 @@ syn keyword cmakeKWfind_package contained
\ ABI
\ BUNDLE
\ CMAKE_DISABLE_FIND_PACKAGE_
+ \ CMAKE_REQUIRE_FIND_PACKAGE_
\ CMAKE_FIND_ROOT_PATH_BOTH
\ COMPONENTS
\ CONFIG
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9944ea4ce..fdfe456aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-cmake_minimum_required(VERSION 3.1...3.19 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.1...3.20 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake)
project(CMake)
@@ -815,8 +815,12 @@ CMAKE_SETUP_TESTING()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
if(NOT CMake_VERSION_IS_RELEASE)
- if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
- NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2)
+ if((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
+ NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 4.2) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND
+ NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS 3.0 AND
+ NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") OR
+ CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set(C_FLAGS_LIST -Wcast-align -Werror-implicit-function-declaration -Wchar-subscripts
-Wall -W -Wpointer-arith -Wwrite-strings -Wformat-security
-Wmissing-format-attribute -fno-common -Wundef
diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst
index 2b902a915..998e14674 100644
--- a/Help/command/cmake_host_system_information.rst
+++ b/Help/command/cmake_host_system_information.rst
@@ -13,46 +13,236 @@ queried. The list of queried values is stored in ``<variable>``.
``<key>`` can be one of the following values:
-============================= ================================================
-Key Description
-============================= ================================================
-``NUMBER_OF_LOGICAL_CORES`` Number of logical cores
-``NUMBER_OF_PHYSICAL_CORES`` Number of physical cores
-``HOSTNAME`` Hostname
-``FQDN`` Fully qualified domain name
-``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in MiB [#mebibytes]_
-``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_
-``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_
-``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_
-============================= ================================================
-
-.. versionadded:: 3.10
- Additional ``<key>`` values are available:
-
-============================= ================================================
-Key Description
-============================= ================================================
-``IS_64BIT`` One if processor is 64Bit
-``HAS_FPU`` One if processor has floating point unit
-``HAS_MMX`` One if processor supports MMX instructions
-``HAS_MMX_PLUS`` One if processor supports Ext. MMX instructions
-``HAS_SSE`` One if processor supports SSE instructions
-``HAS_SSE2`` One if processor supports SSE2 instructions
-``HAS_SSE_FP`` One if processor supports SSE FP instructions
-``HAS_SSE_MMX`` One if processor supports SSE MMX instructions
-``HAS_AMD_3DNOW`` One if processor supports 3DNow instructions
-``HAS_AMD_3DNOW_PLUS`` One if processor supports 3DNow+ instructions
-``HAS_IA64`` One if IA64 processor emulating x86
-``HAS_SERIAL_NUMBER`` One if processor has serial number
-``PROCESSOR_SERIAL_NUMBER`` Processor serial number
-``PROCESSOR_NAME`` Human readable processor name
-``PROCESSOR_DESCRIPTION`` Human readable full processor description
-``OS_NAME`` See :variable:`CMAKE_HOST_SYSTEM_NAME`
-``OS_RELEASE`` The OS sub-type e.g. on Windows ``Professional``
-``OS_VERSION`` The OS build ID
-``OS_PLATFORM`` See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
-============================= ================================================
+``NUMBER_OF_LOGICAL_CORES``
+ Number of logical cores
+
+``NUMBER_OF_PHYSICAL_CORES``
+ Number of physical cores
+
+``HOSTNAME``
+ Hostname
+
+``FQDN``
+ Fully qualified domain name
+
+``TOTAL_VIRTUAL_MEMORY``
+ Total virtual memory in MiB [#mebibytes]_
+
+``AVAILABLE_VIRTUAL_MEMORY``
+ Available virtual memory in MiB [#mebibytes]_
+
+``TOTAL_PHYSICAL_MEMORY``
+ Total physical memory in MiB [#mebibytes]_
+
+``AVAILABLE_PHYSICAL_MEMORY``
+ Available physical memory in MiB [#mebibytes]_
+
+``IS_64BIT``
+ .. versionadded:: 3.10
+
+ One if processor is 64Bit
+
+``HAS_FPU``
+ .. versionadded:: 3.10
+
+ One if processor has floating point unit
+
+``HAS_MMX``
+ .. versionadded:: 3.10
+
+ One if processor supports MMX instructions
+
+``HAS_MMX_PLUS``
+ .. versionadded:: 3.10
+
+ One if processor supports Ext. MMX instructions
+
+``HAS_SSE``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE instructions
+
+``HAS_SSE2``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE2 instructions
+
+``HAS_SSE_FP``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE FP instructions
+
+``HAS_SSE_MMX``
+ .. versionadded:: 3.10
+
+ One if processor supports SSE MMX instructions
+
+``HAS_AMD_3DNOW``
+ .. versionadded:: 3.10
+
+ One if processor supports 3DNow instructions
+
+``HAS_AMD_3DNOW_PLUS``
+ .. versionadded:: 3.10
+
+ One if processor supports 3DNow+ instructions
+
+``HAS_IA64``
+ .. versionadded:: 3.10
+
+ One if IA64 processor emulating x86
+
+``HAS_SERIAL_NUMBER``
+ .. versionadded:: 3.10
+
+ One if processor has serial number
+
+``PROCESSOR_SERIAL_NUMBER``
+ .. versionadded:: 3.10
+
+ Processor serial number
+
+``PROCESSOR_NAME``
+ .. versionadded:: 3.10
+
+ Human readable processor name
+
+``PROCESSOR_DESCRIPTION``
+ .. versionadded:: 3.10
+
+ Human readable full processor description
+
+``OS_NAME``
+ .. versionadded:: 3.10
+
+ See :variable:`CMAKE_HOST_SYSTEM_NAME`
+
+``OS_RELEASE``
+ .. versionadded:: 3.10
+
+ The OS sub-type e.g. on Windows ``Professional``
+
+``OS_VERSION``
+ .. versionadded:: 3.10
+
+ The OS build ID
+
+``OS_PLATFORM``
+ .. versionadded:: 3.10
+
+ See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`
+
+``DISTRIB_INFO``
+ .. versionadded:: 3.22
+
+ Read :file:`/etc/os-release` file and define the given ``<variable>``
+ into a list of read variables
+
+``DISTRIB_<name>``
+ .. versionadded:: 3.22
+
+ Get the ``<name>`` variable (see `man 5 os-release`_) if it exists in the
+ :file:`/etc/os-release` file
+
+ Example:
+
+ .. code-block:: cmake
+
+ cmake_host_system_information(RESULT PRETTY_NAME QUERY DISTRIB_PRETTY_NAME)
+ message(STATUS "${PRETTY_NAME}")
+
+ cmake_host_system_information(RESULT DISTRO QUERY DISTRIB_INFO)
+
+ foreach(VAR IN LISTS DISTRO)
+ message(STATUS "${VAR}=`${${VAR}}`")
+ endforeach()
+
+
+ Output::
+
+ -- Ubuntu 20.04.2 LTS
+ -- DISTRO_BUG_REPORT_URL=`https://bugs.launchpad.net/ubuntu/`
+ -- DISTRO_HOME_URL=`https://www.ubuntu.com/`
+ -- DISTRO_ID=`ubuntu`
+ -- DISTRO_ID_LIKE=`debian`
+ -- DISTRO_NAME=`Ubuntu`
+ -- DISTRO_PRETTY_NAME=`Ubuntu 20.04.2 LTS`
+ -- DISTRO_PRIVACY_POLICY_URL=`https://www.ubuntu.com/legal/terms-and-policies/privacy-policy`
+ -- DISTRO_SUPPORT_URL=`https://help.ubuntu.com/`
+ -- DISTRO_UBUNTU_CODENAME=`focal`
+ -- DISTRO_VERSION=`20.04.2 LTS (Focal Fossa)`
+ -- DISTRO_VERSION_CODENAME=`focal`
+ -- DISTRO_VERSION_ID=`20.04`
+
+If :file:`/etc/os-release` file is not found, the command tries to gather OS
+identification via fallback scripts. The fallback script can use `various
+distribution-specific files`_ to collect OS identification data and map it
+into `man 5 os-release`_ variables.
+
+Fallback Interface Variables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS
+
+ In addition to the scripts shipped with CMake, a user may append full
+ paths to his script(s) to the this list. The script filename has the
+ following format: ``NNN-<name>.cmake``, where ``NNN`` is three digits
+ used to apply collected scripts in a specific order.
+
+.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>
+
+ Variables collected by the user provided fallback script
+ ought to be assigned to CMake variables using this naming
+ convention. Example, the ``ID`` variable from the manual becomes
+ ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID``.
+
+.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+
+ The fallback script ought to store names of all assigned
+ ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>`` variables in this list.
+
+Example:
+
+.. code-block:: cmake
+
+ # Try to detect some old distribution
+ # See also
+ # - http://linuxmafia.com/faq/Admin/release-files.html
+ #
+ if(NOT EXISTS "${CMAKE_SYSROOT}/etc/foobar-release")
+ return()
+ endif()
+ # Get the first string only
+ file(
+ STRINGS "${CMAKE_SYSROOT}/etc/foobar-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+ #
+ # Example:
+ #
+ # Foobar distribution release 1.2.3 (server)
+ #
+ if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "Foobar distribution release ([0-9\.]+) .*")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Foobar)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID foobar)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1})
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+ endif()
+ unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
+
.. rubric:: Footnotes
.. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes.
+
+.. _man 5 os-release: https://www.freedesktop.org/software/systemd/man/os-release.html
+.. _various distribution-specific files: http://linuxmafia.com/faq/Admin/release-files.html
diff --git a/Help/command/configure_file.rst b/Help/command/configure_file.rst
index 086668c16..1d8142351 100644
--- a/Help/command/configure_file.rst
+++ b/Help/command/configure_file.rst
@@ -96,6 +96,7 @@ The arguments are:
with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
If the path names an existing directory the output file is placed
in that directory with the same file name as the input file.
+ If the path contains non-existent directories, they are created.
``NO_SOURCE_PERMISSIONS``
.. versionadded:: 3.19
diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst
index e6d277f59..d66182540 100644
--- a/Help/command/ctest_submit.rst
+++ b/Help/command/ctest_submit.rst
@@ -30,7 +30,8 @@ The options are:
Build = ctest_build results, in Build.xml
Test = ctest_test results, in Test.xml
Coverage = ctest_coverage results, in Coverage.xml
- MemCheck = ctest_memcheck results, in DynamicAnalysis.xml
+ MemCheck = ctest_memcheck results, in DynamicAnalysis.xml and
+ DynamicAnalysis-Test.xml
Notes = Files listed by CTEST_NOTES_FILES, in Notes.xml
ExtraFiles = Files listed by CTEST_EXTRA_SUBMIT_FILES
Upload = Files prepared for upload by ctest_upload(), in Upload.xml
diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index 89787d133..6a9a6a04d 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -190,29 +190,34 @@ Check the `CDash test measurement documentation
<https://github.com/Kitware/CDash/blob/master/docs/test_measurements.md>`_
for more information on the types of test measurements that CDash recognizes.
+.. versionadded: 3.22
+ CTest can parse custom measurements from tags named
+ ``<CTestMeasurement>`` or ``<CTestMeasurementFile>``. The older names
+ ``<DartMeasurement>`` and ``<DartMeasurementFile>`` are still supported.
+
The following example demonstrates how to output a variety of custom test
measurements.
.. code-block:: c++
std::cout <<
- "<DartMeasurement type=\"numeric/double\" name=\"score\">28.3</DartMeasurement>"
+ "<CTestMeasurement type=\"numeric/double\" name=\"score\">28.3</CTestMeasurement>"
<< std::endl;
std::cout <<
- "<DartMeasurement type=\"text/string\" name=\"color\">red</DartMeasurement>"
+ "<CTestMeasurement type=\"text/string\" name=\"color\">red</CTestMeasurement>"
<< std::endl;
std::cout <<
- "<DartMeasurement type=\"text/link\" name=\"CMake URL\">https://cmake.org</DartMeasurement>"
+ "<CTestMeasurement type=\"text/link\" name=\"CMake URL\">https://cmake.org</CTestMeasurement>"
<< std::endl;
std::cout <<
- "<DartMeasurement type=\"text/preformatted\" name=\"Console Output\">" <<
+ "<CTestMeasurement type=\"text/preformatted\" name=\"Console Output\">" <<
"line 1.\n" <<
" \033[31;1m line 2. Bold red, and indented!\033[0;0ml\n" <<
"line 3. Not bold or indented...\n" <<
- "</DartMeasurement>" << std::endl;
+ "</CTestMeasurement>" << std::endl;
Image Measurements
""""""""""""""""""
@@ -222,16 +227,16 @@ The following example demonstrates how to upload test images to CDash.
.. code-block:: c++
std::cout <<
- "<DartMeasurementFile type=\"image/jpg\" name=\"TestImage\">" <<
- "/dir/to/test_img.jpg</DartMeasurementFile>" << std::endl;
+ "<CTestMeasurementFile type=\"image/jpg\" name=\"TestImage\">" <<
+ "/dir/to/test_img.jpg</CTestMeasurementFile>" << std::endl;
std::cout <<
- "<DartMeasurementFile type=\"image/gif\" name=\"ValidImage\">" <<
- "/dir/to/valid_img.gif</DartMeasurementFile>" << std::endl;
+ "<CTestMeasurementFile type=\"image/gif\" name=\"ValidImage\">" <<
+ "/dir/to/valid_img.gif</CTestMeasurementFile>" << std::endl;
std::cout <<
- "<DartMeasurementFile type=\"image/png\" name=\"AlgoResult\"> <<
- "/dir/to/img.png</DartMeasurementFile>"
+ "<CTestMeasurementFile type=\"image/png\" name=\"AlgoResult\"> <<
+ "/dir/to/img.png</CTestMeasurementFile>"
<< std::endl;
Images will be displayed together in an interactive comparison mode on CDash
@@ -252,13 +257,17 @@ separate from the interactive comparison UI.
Attached Files
""""""""""""""
+.. versionadded:: 3.21
+
The following example demonstrates how to upload non-image files to CDash.
.. code-block:: c++
std::cout <<
- "<DartMeasurementFile type=\"file\" name=\"MyTestInputData\">" <<
- "/dir/to/data.csv</DartMeasurementFile>" << std::endl;
+ "<CTestMeasurementFile type=\"file\" name=\"TestInputData1\">" <<
+ "/dir/to/data1.csv</CTestMeasurementFile>\n" <<
+ "<CTestMeasurementFile type=\"file\" name=\"TestInputData2\">" <<
+ "/dir/to/data2.csv</CTestMeasurementFile>" << std::endl;
If the name of the file to upload is known at configure time, you can use the
:prop_test:`ATTACHED_FILES` or :prop_test:`ATTACHED_FILES_ON_FAIL` test
@@ -267,6 +276,8 @@ properties instead.
Custom Details
""""""""""""""
+.. versionadded:: 3.21
+
The following example demonstrates how to specify a custom value for the
``Test Details`` field displayed on CDash.
@@ -274,3 +285,22 @@ The following example demonstrates how to specify a custom value for the
std::cout <<
"<CTestDetails>My Custom Details Value</CTestDetails>" << std::endl;
+
+.. _`Additional Labels`:
+
+Additional Labels
+"""""""""""""""""
+
+.. versionadded:: 3.22
+
+The following example demonstrates how to add additional labels to a test
+at runtime.
+
+.. code-block:: c++
+
+ std::cout <<
+ "<CTestLabel>Custom Label 1</CTestLabel>\n" <<
+ "<CTestLabel>Custom Label 2</CTestLabel>" << std::endl;
+
+Use the :prop_test:`LABELS` test property instead for labels that can be
+determined at configure time.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index f038871b7..799b6ff10 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -838,11 +838,16 @@ of their content even if options are used to select a subset of
files.
The ``INSTALL`` signature differs slightly from ``COPY``: it prints
-status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
-and ``NO_SOURCE_PERMISSIONS`` is default.
+status messages, and ``NO_SOURCE_PERMISSIONS`` is default.
+
Installation scripts generated by the :command:`install` command
use this signature (with some undocumented options for internal use).
+.. versionchanged:: 3.22
+
+ The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the
+ default copying behavior of :command:`file(INSTALL)`.
+
.. _SIZE:
.. code-block:: cmake
@@ -1068,7 +1073,7 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
.. versionadded:: 3.11
Specify whether the .netrc file is to be used for operation. If this
- option is not specified, the value of the ``CMAKE_NETRC`` variable
+ option is not specified, the value of the :variable:`CMAKE_NETRC` variable
will be used instead.
Valid levels are:
@@ -1087,29 +1092,28 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
Specify an alternative .netrc file to the one in your home directory,
if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
- is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
+ is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable will
be used instead.
-If neither ``NETRC`` option is given CMake will check variables
-``CMAKE_NETRC`` and ``CMAKE_NETRC_FILE``, respectively.
-
``TLS_VERIFY <ON|OFF>``
Specify whether to verify the server certificate for ``https://`` URLs.
- The default is to *not* verify.
+ The default is to *not* verify. If this option is not specified, the value
+ of the :variable:`CMAKE_TLS_VERIFY` variable will be used instead.
.. versionadded:: 3.18
Added support to ``file(UPLOAD)``.
``TLS_CAINFO <file>``
- Specify a custom Certificate Authority file for ``https://`` URLs.
+ Specify a custom Certificate Authority file for ``https://`` URLs. If this
+ option is not specified, the value of the :variable:`CMAKE_TLS_CAINFO`
+ variable will be used instead.
.. versionadded:: 3.18
Added support to ``file(UPLOAD)``.
For ``https://`` URLs CMake must be built with OpenSSL support. ``TLS/SSL``
certificates are not checked by default. Set ``TLS_VERIFY`` to ``ON`` to
-check certificates. If neither ``TLS`` option is given CMake will check
-variables :variable:`CMAKE_TLS_VERIFY` and ``CMAKE_TLS_CAINFO``, respectively.
+check certificates.
Additional options to ``DOWNLOAD`` are:
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 3dfd62fc3..1a79a8af3 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -5,12 +5,74 @@ find_package
.. contents::
-Find an external project, and load its settings.
+Find a package (usually provided by something external to the project),
+and load its package-specific details.
+
+Search Modes
+^^^^^^^^^^^^
+
+The command has two very distinct ways of conducting the search:
+
+**Module mode**
+ In this mode, CMake searches for a file called ``Find<PackageName>.cmake``,
+ looking first in the locations listed in the :variable:`CMAKE_MODULE_PATH`,
+ then among the :ref:`Find Modules` provided by the CMake installation.
+ If the file is found, it is read and processed by CMake. It is responsible
+ for finding the package, checking the version, and producing any needed
+ messages. Some Find modules provide limited or no support for versioning;
+ check the Find module's documentation.
+
+ The ``Find<PackageName>.cmake`` file is not typically provided by the
+ package itself. Rather, it is normally provided by something external to
+ the package, such as the operating system, CMake itself, or even the project
+ from which the ``find_package()`` command was called. Being externally
+ provided, :ref:`Find Modules` tend to be heuristic in nature and are
+ susceptible to becoming out-of-date. They typically search for certain
+ libraries, files and other package artifacts.
+
+ Module mode is only supported by the
+ :ref:`basic command signature <Basic Signature>`.
+
+**Config mode**
+ In this mode, CMake searches for a file called
+ ``<lowercasePackageName>-config.cmake`` or ``<PackageName>Config.cmake``.
+ It will also look for ``<lowercasePackageName>-config-version.cmake`` or
+ ``<PackageName>ConfigVersion.cmake`` if version details were specified
+ (see :ref:`version selection` for an explanation of how these separate
+ version files are used).
+
+ In config mode, the command can be given a list of names to search for
+ as package names. The locations where CMake searches for the config and
+ version files is considerably more complicated than for Module mode
+ (see :ref:`search procedure`).
+
+ The config and version files are typically installed as part of the
+ package, so they tend to be more reliable than Find modules. They usually
+ contain direct knowledge of the package contents, so no searching or
+ heuristics are needed within the config or version files themselves.
+
+ Config mode is supported by both the :ref:`basic <Basic Signature>` and
+ :ref:`full <Full Signature>` command signatures.
+
+The command arguments determine which of the above modes is used. When the
+`basic signature`_ is used, the command searches in Module mode first.
+If the package is not found, the search falls back to Config mode.
+A user may set the :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` variable
+to true to reverse the priority and direct CMake to search using Config mode
+first before falling back to Module mode. The basic signature can also be
+forced to use only Module mode with a ``MODULE`` keyword. If the
+`full signature`_ is used, the command only searches in Config mode.
+
+Where possible, user code should generally look for packages using the
+`basic signature`_, since that allows the package to be found with either mode.
+Project maintainers wishing to provide a config package should understand
+the bigger picture, as explained in :ref:`Full Signature` and all subsequent
+sections on this page.
.. _`basic signature`:
-Basic Signature and Module Mode
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Basic Signature
+^^^^^^^^^^^^^^^
.. code-block:: cmake
@@ -19,20 +81,39 @@ Basic Signature and Module Mode
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
-Finds and loads settings from an external project. ``<PackageName>_FOUND``
-will be set to indicate whether the package was found. When the
-package is found package-specific information is provided through
-variables and :ref:`Imported Targets` documented by the package itself. The
+The basic signature is supported by both Module and Config modes.
+The ``MODULE`` keyword implies that only Module mode can be used to find
+the package, with no fallback to Config mode.
+
+Regardless of the mode used, a ``<PackageName>_FOUND`` variable will be
+set to indicate whether the package was found. When the package is found,
+package-specific information may be provided through other variables and
+:ref:`Imported Targets` documented by the package itself. The
``QUIET`` option disables informational messages, including those indicating
that the package cannot be found if it is not ``REQUIRED``. The ``REQUIRED``
option stops processing with an error message if the package cannot be found.
A package-specific list of required components may be listed after the
-``COMPONENTS`` option (or after the ``REQUIRED`` option if present).
+``COMPONENTS`` keyword. If any of these components are not able to be
+satisfied, the package overall is considered to be not found. If the
+``REQUIRED`` option is also present, this is treated as a fatal error,
+otherwise execution still continues. As a form of shorthand, if the
+``REQUIRED`` option is present, the ``COMPONENTS`` keyword can be omitted
+and the required components can be listed directly after ``REQUIRED``.
+
Additional optional components may be listed after
-``OPTIONAL_COMPONENTS``. Available components and their influence on
-whether a package is considered to be found are defined by the target
-package.
+``OPTIONAL_COMPONENTS``. If these cannot be satisfied, the package overall
+can still be considered found, as long as all required components are
+satisfied.
+
+The set of available components and their meaning are defined by the
+target package. Formally, it is up to the target package how to
+interpret the component information given to it, but it should follow
+the expectations stated above. For calls where no components are specified,
+there is no single expected behavior and target packages should clearly
+define what occurs in such cases. Common arrangements include assuming it
+should find all components, no components or some well-defined subset of the
+available components.
.. _FIND_PACKAGE_VERSION_FORMAT:
@@ -40,12 +121,13 @@ The ``[version]`` argument requests a version with which the package found
should be compatible. There are two possible forms in which it may be
specified:
- * A single version with the format ``major[.minor[.patch[.tweak]]]``.
+ * A single version with the format ``major[.minor[.patch[.tweak]]]``, where
+ each component is a numeric value.
* A version range with the format ``versionMin...[<]versionMax`` where
- ``versionMin`` and ``versionMax`` have the same format as the single
- version. By default, both end points are included. By specifying ``<``,
- the upper end point will be excluded. Version ranges are only supported
- with CMake 3.19 or later.
+ ``versionMin`` and ``versionMax`` have the same format and constraints
+ on components being integers as the single version. By default, both end
+ points are included. By specifying ``<``, the upper end point will be
+ excluded. Version ranges are only supported with CMake 3.19 or later.
The ``EXACT`` option requests that the version be matched exactly. This option
is incompatible with the specification of a version range.
@@ -62,36 +144,10 @@ only take the single version at the lower end of the range into account.
See the :command:`cmake_policy` command documentation for discussion
of the ``NO_POLICY_SCOPE`` option.
-The command has two modes by which it searches for packages: "Module"
-mode and "Config" mode. The above signature selects Module mode.
-If no module is found the command falls back to Config mode, described
-below. This fall back is disabled if the ``MODULE`` option is given.
-
-In Module mode, CMake searches for a file called ``Find<PackageName>.cmake``.
-The file is first searched in the :variable:`CMAKE_MODULE_PATH`,
-then among the :ref:`Find Modules` provided by the CMake installation.
-If the file is found, it is read and processed by CMake. It is responsible
-for finding the package, checking the version, and producing any needed
-messages. Some find-modules provide limited or no support for versioning;
-check the module documentation.
-
-If the ``MODULE`` option is not specified in the above signature,
-CMake first searches for the package using Module mode. Then, if the
-package is not found, it searches again using Config mode. A user
-may set the variable :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` to
-``TRUE`` to direct CMake first search using Config mode before falling
-back to Module mode.
-
-Full Signature and Config Mode
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-User code should generally look for packages using the above `basic
-signature`_. The remainder of this command documentation specifies the
-full command signature and details of the search process. Project
-maintainers wishing to provide a package to be found by this command
-are encouraged to read on.
-
-The complete Config mode command signature is
+.. _`full signature`:
+
+Full Signature
+^^^^^^^^^^^^^^
.. code-block:: cmake
@@ -129,18 +185,19 @@ hold the directory containing the file. By default the command
searches for a package with the name ``<PackageName>``. If the ``NAMES`` option
is given the names following it are used instead of ``<PackageName>``.
The command searches for a file called ``<PackageName>Config.cmake`` or
-``<lower-case-package-name>-config.cmake`` for each name specified.
+``<lowercasePackageName>-config.cmake`` for each name specified.
A replacement set of possible configuration file names may be given
-using the ``CONFIGS`` option. The search procedure is specified below.
-Once found, the configuration file is read and processed by CMake.
+using the ``CONFIGS`` option. The :ref:`search procedure` is specified below.
+Once found, any :ref:`version constraint <version selection>` is checked,
+and if satisfied, the configuration file is read and processed by CMake.
Since the file is provided by the package it already knows the
location of package contents. The full path to the configuration file
is stored in the cmake variable ``<PackageName>_CONFIG``.
All configuration files which have been considered by CMake while
-searching for an installation of the package with an appropriate
-version are stored in the cmake variable ``<PackageName>_CONSIDERED_CONFIGS``,
-the associated versions in ``<PackageName>_CONSIDERED_VERSIONS``.
+searching for the package with an appropriate version are stored in the
+``<PackageName>_CONSIDERED_CONFIGS`` variable, and the associated versions
+in the ``<PackageName>_CONSIDERED_VERSIONS`` variable.
If the package configuration file cannot be found CMake will generate
an error describing the problem unless the ``QUIET`` argument is
@@ -150,143 +207,18 @@ fatal error is generated and the configure step stops executing. If
configuration file CMake will ignore it and search from scratch.
Package maintainers providing CMake package configuration files are
-encouraged to name and install them such that the `Search Procedure`_
+encouraged to name and install them such that the :ref:`search procedure`
outlined below will find them without requiring use of additional options.
-Version Selection
-^^^^^^^^^^^^^^^^^
+.. _`search procedure`:
-When the ``[version]`` argument is given, Config mode will only find a
-version of the package that claims compatibility with the requested
-version (see :ref:`format specification <FIND_PACKAGE_VERSION_FORMAT>`). If the
-``EXACT`` option is given, only a version of the package claiming an exact match
-of the requested version may be found. CMake does not establish any
-convention for the meaning of version numbers. Package version
-numbers are checked by "version" files provided by the packages
-themselves. For a candidate package configuration file
-``<config-file>.cmake`` the corresponding version file is located next
-to it and named either ``<config-file>-version.cmake`` or
-``<config-file>Version.cmake``. If no such version file is available
-then the configuration file is assumed to not be compatible with any
-requested version. A basic version file containing generic version
-matching code can be created using the
-:module:`CMakePackageConfigHelpers` module. When a version file
-is found it is loaded to check the requested version number. The
-version file is loaded in a nested scope in which the following
-variables have been defined:
+Config Mode Search Procedure
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-``PACKAGE_FIND_NAME``
- The ``<PackageName>``
-``PACKAGE_FIND_VERSION``
- Full requested version string
-``PACKAGE_FIND_VERSION_MAJOR``
- Major version if requested, else 0
-``PACKAGE_FIND_VERSION_MINOR``
- Minor version if requested, else 0
-``PACKAGE_FIND_VERSION_PATCH``
- Patch version if requested, else 0
-``PACKAGE_FIND_VERSION_TWEAK``
- Tweak version if requested, else 0
-``PACKAGE_FIND_VERSION_COUNT``
- Number of version components, 0 to 4
-
-When a version range is specified, the above version variables will hold
-values based on the lower end of the version range. This is to preserve
-compatibility with packages that have not been implemented to expect version
-ranges. In addition, the version range will be described by the following
-variables:
-
-``PACKAGE_FIND_VERSION_RANGE``
- Full requested version range string
-``PACKAGE_FIND_VERSION_RANGE_MIN``
- This specifies whether the lower end point of the version range should be
- included or excluded. Currently, the only supported value for this variable
- is ``INCLUDE``.
-``PACKAGE_FIND_VERSION_RANGE_MAX``
- This specifies whether the upper end point of the version range should be
- included or excluded. The supported values for this variable are
- ``INCLUDE`` and ``EXCLUDE``.
-
-``PACKAGE_FIND_VERSION_MIN``
- Full requested version string of the lower end point of the range
-``PACKAGE_FIND_VERSION_MIN_MAJOR``
- Major version of the lower end point if requested, else 0
-``PACKAGE_FIND_VERSION_MIN_MINOR``
- Minor version of the lower end point if requested, else 0
-``PACKAGE_FIND_VERSION_MIN_PATCH``
- Patch version of the lower end point if requested, else 0
-``PACKAGE_FIND_VERSION_MIN_TWEAK``
- Tweak version of the lower end point if requested, else 0
-``PACKAGE_FIND_VERSION_MIN_COUNT``
- Number of version components of the lower end point, 0 to 4
-
-``PACKAGE_FIND_VERSION_MAX``
- Full requested version string of the upper end point of the range
-``PACKAGE_FIND_VERSION_MAX_MAJOR``
- Major version of the upper end point if requested, else 0
-``PACKAGE_FIND_VERSION_MAX_MINOR``
- Minor version of the upper end point if requested, else 0
-``PACKAGE_FIND_VERSION_MAX_PATCH``
- Patch version of the upper end point if requested, else 0
-``PACKAGE_FIND_VERSION_MAX_TWEAK``
- Tweak version of the upper end point if requested, else 0
-``PACKAGE_FIND_VERSION_MAX_COUNT``
- Number of version components of the upper end point, 0 to 4
-
-Regardless of whether a single version or a version range is specified, the
-variable ``PACKAGE_FIND_VERSION_COMPLETE`` will be defined and will hold
-the full requested version string as specified.
-
-The version file checks whether it satisfies the requested version and
-sets these variables:
-
-``PACKAGE_VERSION``
- Full provided version string
-``PACKAGE_VERSION_EXACT``
- True if version is exact match
-``PACKAGE_VERSION_COMPATIBLE``
- True if version is compatible
-``PACKAGE_VERSION_UNSUITABLE``
- True if unsuitable as any version
-
-These variables are checked by the ``find_package`` command to determine
-whether the configuration file provides an acceptable version. They
-are not available after the ``find_package`` call returns. If the version
-is acceptable the following variables are set:
-
-``<PackageName>_VERSION``
- Full provided version string
-``<PackageName>_VERSION_MAJOR``
- Major version if provided, else 0
-``<PackageName>_VERSION_MINOR``
- Minor version if provided, else 0
-``<PackageName>_VERSION_PATCH``
- Patch version if provided, else 0
-``<PackageName>_VERSION_TWEAK``
- Tweak version if provided, else 0
-``<PackageName>_VERSION_COUNT``
- Number of version components, 0 to 4
-
-and the corresponding package configuration file is loaded.
-When multiple package configuration files are available whose version files
-claim compatibility with the version requested it is unspecified which
-one is chosen: unless the variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`
-is set no attempt is made to choose a highest or closest version number.
-
-To control the order in which ``find_package`` checks for compatibility use
-the two variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and
-:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`.
-For instance in order to select the highest version one can set
-
-.. code-block:: cmake
-
- SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
- SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
-
-before calling ``find_package``.
-
-Search Procedure
-^^^^^^^^^^^^^^^^
+.. note::
+ When Config mode is used, this search procedure is applied regardless of
+ whether the :ref:`full <full signature>` or :ref:`basic <basic signature>`
+ signature was given.
CMake constructs a set of possible installation prefixes for the
package. Under each prefix several directories are searched for a
@@ -432,7 +364,7 @@ enabled.
hard-coded guesses.
.. versionadded:: 3.16
- Added the ``CMAKE_FIND_USE_<CATEGORY>_PATH`` variables to globally disable
+ Added the ``CMAKE_FIND_USE_<CATEGORY>`` variables to globally disable
various search locations.
.. |FIND_XXX| replace:: find_package
@@ -448,8 +380,154 @@ which the file is found. The :variable:`CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS`
variable may be set to ``TRUE`` before calling ``find_package`` in order
to resolve symbolic links and store the real path to the file.
-Every non-REQUIRED ``find_package`` call can be disabled by setting the
-:variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to ``TRUE``.
+Every non-REQUIRED ``find_package`` call can be disabled or made REQUIRED:
+
+* Setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable
+ to ``TRUE`` disables the package.
+
+* Setting the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable
+ to ``TRUE`` makes the package REQUIRED.
+
+Setting both variables to ``TRUE`` simultaneously is an error.
+
+.. _`version selection`:
+
+Config Mode Version Selection
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. note::
+ When Config mode is used, this version selection process is applied
+ regardless of whether the :ref:`full <full signature>` or
+ :ref:`basic <basic signature>` signature was given.
+
+When the ``[version]`` argument is given, Config mode will only find a
+version of the package that claims compatibility with the requested
+version (see :ref:`format specification <FIND_PACKAGE_VERSION_FORMAT>`). If the
+``EXACT`` option is given, only a version of the package claiming an exact match
+of the requested version may be found. CMake does not establish any
+convention for the meaning of version numbers. Package version
+numbers are checked by "version" files provided by the packages
+themselves. For a candidate package configuration file
+``<config-file>.cmake`` the corresponding version file is located next
+to it and named either ``<config-file>-version.cmake`` or
+``<config-file>Version.cmake``. If no such version file is available
+then the configuration file is assumed to not be compatible with any
+requested version. A basic version file containing generic version
+matching code can be created using the
+:module:`CMakePackageConfigHelpers` module. When a version file
+is found it is loaded to check the requested version number. The
+version file is loaded in a nested scope in which the following
+variables have been defined:
+
+``PACKAGE_FIND_NAME``
+ The ``<PackageName>``
+``PACKAGE_FIND_VERSION``
+ Full requested version string
+``PACKAGE_FIND_VERSION_MAJOR``
+ Major version if requested, else 0
+``PACKAGE_FIND_VERSION_MINOR``
+ Minor version if requested, else 0
+``PACKAGE_FIND_VERSION_PATCH``
+ Patch version if requested, else 0
+``PACKAGE_FIND_VERSION_TWEAK``
+ Tweak version if requested, else 0
+``PACKAGE_FIND_VERSION_COUNT``
+ Number of version components, 0 to 4
+
+When a version range is specified, the above version variables will hold
+values based on the lower end of the version range. This is to preserve
+compatibility with packages that have not been implemented to expect version
+ranges. In addition, the version range will be described by the following
+variables:
+
+``PACKAGE_FIND_VERSION_RANGE``
+ Full requested version range string
+``PACKAGE_FIND_VERSION_RANGE_MIN``
+ This specifies whether the lower end point of the version range should be
+ included or excluded. Currently, the only supported value for this variable
+ is ``INCLUDE``.
+``PACKAGE_FIND_VERSION_RANGE_MAX``
+ This specifies whether the upper end point of the version range should be
+ included or excluded. The supported values for this variable are
+ ``INCLUDE`` and ``EXCLUDE``.
+
+``PACKAGE_FIND_VERSION_MIN``
+ Full requested version string of the lower end point of the range
+``PACKAGE_FIND_VERSION_MIN_MAJOR``
+ Major version of the lower end point if requested, else 0
+``PACKAGE_FIND_VERSION_MIN_MINOR``
+ Minor version of the lower end point if requested, else 0
+``PACKAGE_FIND_VERSION_MIN_PATCH``
+ Patch version of the lower end point if requested, else 0
+``PACKAGE_FIND_VERSION_MIN_TWEAK``
+ Tweak version of the lower end point if requested, else 0
+``PACKAGE_FIND_VERSION_MIN_COUNT``
+ Number of version components of the lower end point, 0 to 4
+
+``PACKAGE_FIND_VERSION_MAX``
+ Full requested version string of the upper end point of the range
+``PACKAGE_FIND_VERSION_MAX_MAJOR``
+ Major version of the upper end point if requested, else 0
+``PACKAGE_FIND_VERSION_MAX_MINOR``
+ Minor version of the upper end point if requested, else 0
+``PACKAGE_FIND_VERSION_MAX_PATCH``
+ Patch version of the upper end point if requested, else 0
+``PACKAGE_FIND_VERSION_MAX_TWEAK``
+ Tweak version of the upper end point if requested, else 0
+``PACKAGE_FIND_VERSION_MAX_COUNT``
+ Number of version components of the upper end point, 0 to 4
+
+Regardless of whether a single version or a version range is specified, the
+variable ``PACKAGE_FIND_VERSION_COMPLETE`` will be defined and will hold
+the full requested version string as specified.
+
+The version file checks whether it satisfies the requested version and
+sets these variables:
+
+``PACKAGE_VERSION``
+ Full provided version string
+``PACKAGE_VERSION_EXACT``
+ True if version is exact match
+``PACKAGE_VERSION_COMPATIBLE``
+ True if version is compatible
+``PACKAGE_VERSION_UNSUITABLE``
+ True if unsuitable as any version
+
+These variables are checked by the ``find_package`` command to determine
+whether the configuration file provides an acceptable version. They
+are not available after the ``find_package`` call returns. If the version
+is acceptable the following variables are set:
+
+``<PackageName>_VERSION``
+ Full provided version string
+``<PackageName>_VERSION_MAJOR``
+ Major version if provided, else 0
+``<PackageName>_VERSION_MINOR``
+ Minor version if provided, else 0
+``<PackageName>_VERSION_PATCH``
+ Patch version if provided, else 0
+``<PackageName>_VERSION_TWEAK``
+ Tweak version if provided, else 0
+``<PackageName>_VERSION_COUNT``
+ Number of version components, 0 to 4
+
+and the corresponding package configuration file is loaded.
+When multiple package configuration files are available whose version files
+claim compatibility with the version requested it is unspecified which
+one is chosen: unless the variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`
+is set no attempt is made to choose a highest or closest version number.
+
+To control the order in which ``find_package`` checks for compatibility use
+the two variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and
+:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`.
+For instance in order to select the highest version one can set
+
+.. code-block:: cmake
+
+ SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
+ SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
+
+before calling ``find_package``.
Package File Interface Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -479,7 +557,7 @@ restores their original state before returning):
``<PackageName>_FIND_VERSION_EXACT``
True if ``EXACT`` option was given
``<PackageName>_FIND_COMPONENTS``
- List of requested components
+ List of specified components (required and optional)
``<PackageName>_FIND_REQUIRED_<c>``
True if component ``<c>`` is required,
false if component ``<c>`` is optional
diff --git a/Help/command/get_property.rst b/Help/command/get_property.rst
index f77d8af78..46da2853b 100644
--- a/Help/command/get_property.rst
+++ b/Help/command/get_property.rst
@@ -9,7 +9,7 @@ Get a property.
<GLOBAL |
DIRECTORY [<dir>] |
TARGET <target> |
- SOURCE <source> |
+ SOURCE <source>
[DIRECTORY <dir> | TARGET_DIRECTORY <target>] |
INSTALL <file> |
TEST <test> |
diff --git a/Help/command/if.rst b/Help/command/if.rst
index fbf3e363f..6ff8852a3 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -171,7 +171,7 @@ Comparisons
``if(<variable|string> MATCHES regex)``
True if the given string or variable's value matches the given regular
- condition. See :ref:`Regex Specification` for regex format.
+ expression. See :ref:`Regex Specification` for regex format.
.. versionadded:: 3.9
``()`` groups are captured in :variable:`CMAKE_MATCH_<n>` variables.
diff --git a/Help/command/install.rst b/Help/command/install.rst
index c6af4897e..1236f1d32 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -30,6 +30,10 @@ are executed in order during installation.
with those in the parent directory to run in the order declared (see
policy :policy:`CMP0082`).
+.. versionchanged:: 3.22
+ The environment variable :envvar:`CMAKE_INSTALL_MODE` can override the
+ default copying behavior of :command:`install()`.
+
There are multiple signatures for this command. Some of them define
installation options for files and targets. Options common to
multiple signatures are covered here but they are valid only for
diff --git a/Help/command/list.rst b/Help/command/list.rst
index f46641f0b..9b49cb493 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -161,8 +161,9 @@ Inserts elements to the list to the specified location.
.. versionadded:: 3.15
If no variable name is given, removes exactly one element. Otherwise,
-assign the last element's value to the given variable and removes it,
-up to the last variable name given.
+with `N` variable names provided, assign the last `N` elements' values
+to the given variables and then remove the last `N` values from
+``<list>``.
.. _POP_FRONT:
@@ -173,8 +174,9 @@ up to the last variable name given.
.. versionadded:: 3.15
If no variable name is given, removes exactly one element. Otherwise,
-assign the first element's value to the given variable and removes it,
-up to the last variable name given.
+with `N` variable names provided, assign the first `N` elements' values
+to the given variables and then remove the first `N` values from
+``<list>``.
.. _PREPEND:
diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst
index bf437b434..555520d22 100644
--- a/Help/command/set_property.rst
+++ b/Help/command/set_property.rst
@@ -9,8 +9,8 @@ Set a named property in a given scope.
DIRECTORY [<dir>] |
TARGET [<target1> ...] |
SOURCE [<src1> ...]
- [DIRECTORY <dirs> ...] |
- [TARGET_DIRECTORY <targets> ...]
+ [DIRECTORY <dirs> ...]
+ [TARGET_DIRECTORY <targets> ...] |
INSTALL [<file1> ...] |
TEST [<test1> ...] |
CACHE [<entry1> ...] >
diff --git a/Help/command/source_group.rst b/Help/command/source_group.rst
index a4b5bf1c6..83ae2864c 100644
--- a/Help/command/source_group.rst
+++ b/Help/command/source_group.rst
@@ -22,7 +22,8 @@ The options are:
CMake will automatically detect, from ``<src>`` files paths, source groups
it needs to create, to keep structure of source groups analogically to the
actual files and directories structure in the project. Paths of ``<src>``
- files will be cut to be relative to ``<root>``.
+ files will be cut to be relative to ``<root>``. The command fails if the
+ paths within ``src`` do not start with ``root``.
``PREFIX``
.. versionadded:: 3.8
diff --git a/Help/command/string.rst b/Help/command/string.rst
index 8ad0089af..29ad082a9 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -449,38 +449,73 @@ be in Coordinated Universal Time (UTC) rather than local time.
The optional ``<format_string>`` may contain the following format
specifiers:
-::
+``%%``
+ .. versionadded:: 3.8
- %% A literal percent sign (%).
- %d The day of the current month (01-31).
- %H The hour on a 24-hour clock (00-23).
- %I The hour on a 12-hour clock (01-12).
- %j The day of the current year (001-366).
- %m The month of the current year (01-12).
- %b Abbreviated month name (e.g. Oct).
- %B Full month name (e.g. October).
- %M The minute of the current hour (00-59).
- %s Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).
- %S The second of the current minute.
- 60 represents a leap second. (00-60)
- %U The week number of the current year (00-53).
- %w The day of the current week. 0 is Sunday. (0-6)
- %a Abbreviated weekday name (e.g. Fri).
- %A Full weekday name (e.g. Friday).
- %y The last two digits of the current year (00-99)
- %Y The current year.
-
-.. versionadded:: 3.6
- ``%s`` format specifier (UNIX time).
+ A literal percent sign (%).
-.. versionadded:: 3.7
- ``%a`` and ``%b`` format specifiers (abbreviated month and weekday names).
+``%d``
+ The day of the current month (01-31).
-.. versionadded:: 3.8
- ``%%`` specifier (literal ``%``).
+``%H``
+ The hour on a 24-hour clock (00-23).
-.. versionadded:: 3.7
- ``%A`` and ``%B`` format specifiers (full month and weekday names).
+``%I``
+ The hour on a 12-hour clock (01-12).
+
+``%j``
+ The day of the current year (001-366).
+
+``%m``
+ The month of the current year (01-12).
+
+``%b``
+ .. versionadded:: 3.7
+
+ Abbreviated month name (e.g. Oct).
+
+``%B``
+ .. versionadded:: 3.10
+
+ Full month name (e.g. October).
+
+``%M``
+ The minute of the current hour (00-59).
+
+``%s``
+ .. versionadded:: 3.6
+
+ Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).
+
+``%S``
+ The second of the current minute. 60 represents a leap second. (00-60)
+
+``%U``
+ The week number of the current year (00-53).
+
+``%V``
+ .. versionadded:: 3.22
+
+ The ISO 8601 week number of the current year (01-53).
+
+``%w``
+ The day of the current week. 0 is Sunday. (0-6)
+
+``%a``
+ .. versionadded:: 3.7
+
+ Abbreviated weekday name (e.g. Fri).
+
+``%A``
+ .. versionadded:: 3.10
+
+ Full weekday name (e.g. Friday).
+
+``%y``
+ The last two digits of the current year (00-99).
+
+``%Y``
+ The current year.
Unknown format specifiers will be ignored and copied to the output
as-is.
diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst
index 08f8d5b62..06da910dd 100644
--- a/Help/command/try_compile.rst
+++ b/Help/command/try_compile.rst
@@ -19,6 +19,10 @@ Try Compiling Whole Projects
Try building a project. The success or failure of the ``try_compile``,
i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``.
+.. versionadded:: 3.14
+ The name of the ``<resultVar>`` is defined by the user. Previously, it had
+ a fixed name ``RESULT_VAR``.
+
In this form, ``<srcdir>`` should contain a complete CMake project with a
``CMakeLists.txt`` file and all sources. The ``<bindir>`` and ``<srcdir>``
will not be deleted after this command is run. Specify ``<targetName>`` to
@@ -47,6 +51,10 @@ Try building an executable or static library from one or more source files
variable). The success or failure of the ``try_compile``, i.e. ``TRUE`` or
``FALSE`` respectively, is returned in ``<resultVar>``.
+.. versionadded:: 3.14
+ The name of the ``<resultVar>`` is defined by the user. Previously, it had
+ a fixed name ``RESULT_VAR``.
+
In this form, one or more source files must be provided. If
:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to ``EXECUTABLE``,
the sources must include a definition for ``main`` and CMake will create a
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index fc41cdd7b..404de985d 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -30,6 +30,11 @@ executable was built, but failed to run, then ``<runResultVar>`` will be
set to ``FAILED_TO_RUN``. See the :command:`try_compile` command for
information on how the test project is constructed to build the source file.
+.. versionadded:: 3.14
+ The names of the result variables ``<runResultVar>`` and
+ ``<compileResultVar>`` are defined by the user. Previously, they had
+ fixed names ``RUN_RESULT_VAR`` and ``COMPILE_RESULT_VAR``.
+
The options are:
``CMAKE_FLAGS <flags>...``
diff --git a/Help/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index d8d53ece3..f96ca3203 100644
--- a/Help/cpack_gen/deb.rst
+++ b/Help/cpack_gen/deb.rst
@@ -274,10 +274,23 @@ List of CPack DEB generator specific variables:
Possible values are:
- - lzma
- - xz
- - bzip2
- - gzip
+ ``lzma``
+ Lempel–Ziv–Markov chain algorithm
+
+ ``xz``
+ XZ Utils compression
+
+ ``bzip2``
+ bzip2 Burrows–Wheeler algorithm
+
+ ``gzip``
+ GNU Gzip compression
+
+ ``zstd``
+ .. versionadded:: 3.22
+
+ Zstandard compression
+
.. variable:: CPACK_DEBIAN_PACKAGE_PRIORITY
CPACK_DEBIAN_<COMPONENT>_PACKAGE_PRIORITY
@@ -652,9 +665,18 @@ Dbgsym packaging has its own set of variables:
.. note::
+ Setting this also strips the ELF files in the generated non-dbgsym package,
+ which results in debuginfo only being available in the dbgsym package.
+
+.. note::
+
Binaries must contain debug symbols before packaging so use either ``Debug``
or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
+ Additionally, if :variable:`CPACK_STRIP_FILES` is set, the files will be stripped before
+ they get to the DEB generator, so will not contain debug symbols and
+ a dbgsym package will not get built. Do not use with :variable:`CPACK_STRIP_FILES`.
+
Building Debian packages on Windows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index 02e33ba30..299cfece9 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -3,8 +3,8 @@ CPack NSIS Generator
CPack Nullsoft Scriptable Install System (NSIS) generator specific options.
-.. versionchanged:: 3.17
- The NSIS generator requires NSIS 3.0 or newer.
+.. versionchanged:: 3.22
+ The NSIS generator requires NSIS 3.03 or newer.
Variables specific to CPack NSIS generator
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -201,3 +201,9 @@ on Windows Nullsoft Scriptable Install System.
.. versionadded:: 3.21
If set, specify the name of the NSIS executable. Default is ``makensis``.
+
+.. variable:: CPACK_NSIS_IGNORE_LICENSE_PAGE
+
+ .. versionadded:: 3.22
+
+ If set, do not display the page containing the license during installation.
diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst
index 322ab68aa..0d287fc91 100644
--- a/Help/cpack_gen/rpm.rst
+++ b/Help/cpack_gen/rpm.rst
@@ -840,6 +840,10 @@ Debuginfo RPM packaging has its own set of variables:
Binaries must contain debug symbols before packaging so use either ``Debug``
or ``RelWithDebInfo`` for :variable:`CMAKE_BUILD_TYPE` variable value.
+ Additionally, if :variable:`CPACK_STRIP_FILES` is set, the files will be stripped before
+ they get to the RPM generator, so will not contain debug symbols and
+ a debuginfo package will not get built. Do not use with :variable:`CPACK_STRIP_FILES`.
+
.. note::
Packages generated from packages without binary files, with binary files but
@@ -1023,7 +1027,7 @@ Source RPM packaging has its own set of variables:
* Mandatory : YES
* Default : "/"
-.. VARIABLE:: CPACK_RPM_BUILDREQUIRES
+.. variable:: CPACK_RPM_BUILDREQUIRES
List of source rpm build dependencies.
@@ -1035,3 +1039,16 @@ Source RPM packaging has its own set of variables:
example::
set(CPACK_RPM_BUILDREQUIRES "python >= 2.5.0, cmake >= 2.8")
+
+.. variable:: CPACK_RPM_REQUIRES_EXCLUDE_FROM
+
+ .. versionadded:: 3.22
+
+ * Mandatory : NO
+ * Default : -
+
+ May be used to keep the dependency generator from scanning specific files
+ or directories for dependencies. Note that you can use a regular
+ expression that matches all of the directories or files, for example::
+
+ set(CPACK_RPM_REQUIRES_EXCLUDE_FROM "bin/libqsqloci.*\\.so.*")
diff --git a/Help/dev/documentation.rst b/Help/dev/documentation.rst
index 29fc88033..4a2a5d963 100644
--- a/Help/dev/documentation.rst
+++ b/Help/dev/documentation.rst
@@ -92,6 +92,11 @@ literal block after ``::``
the referenced documents inline as part of the referencing
document.
+``versionadded``, ``versionchanged`` directives
+ Specify that something was added or changed by a named CMake version.
+ The command-line help processor prints the block content as if the lines
+ were normal paragraph text with interpretation.
+
Inline markup constructs not listed above are printed literally in the
command-line help output. We prefer to use inline markup constructs that
look correct in source form, so avoid use of \\-escapes in favor of inline
diff --git a/Help/envvar/CMAKE_BUILD_TYPE.rst b/Help/envvar/CMAKE_BUILD_TYPE.rst
new file mode 100644
index 000000000..f798aff1f
--- /dev/null
+++ b/Help/envvar/CMAKE_BUILD_TYPE.rst
@@ -0,0 +1,10 @@
+CMAKE_BUILD_TYPE
+----------------
+
+.. versionadded:: 3.22
+
+.. include:: ENV_VAR.txt
+
+The ``CMAKE_BUILD_TYPE`` environment variable specifies a default value
+for the :variable:`CMAKE_BUILD_TYPE` variable when there is no explicit
+configuration given on the first run while creating a new build tree.
diff --git a/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst b/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst
new file mode 100644
index 000000000..833aa4a9f
--- /dev/null
+++ b/Help/envvar/CMAKE_CONFIGURATION_TYPES.rst
@@ -0,0 +1,11 @@
+CMAKE_CONFIGURATION_TYPES
+-------------------------
+
+.. versionadded:: 3.22
+
+.. include:: ENV_VAR.txt
+
+The ``CMAKE_CONFIGURATION_TYPES`` environment variable specifies a
+default value for the :variable:`CMAKE_CONFIGURATION_TYPES` variable
+when there is no explicit configuration given on the first run while
+creating a new build tree.
diff --git a/Help/envvar/CMAKE_INSTALL_MODE.rst b/Help/envvar/CMAKE_INSTALL_MODE.rst
new file mode 100644
index 000000000..37db0d714
--- /dev/null
+++ b/Help/envvar/CMAKE_INSTALL_MODE.rst
@@ -0,0 +1,37 @@
+CMAKE_INSTALL_MODE
+------------------
+
+.. versionadded:: 3.22
+
+.. include:: ENV_VAR.txt
+
+The ``CMAKE_INSTALL_MODE`` environment variable allows users to operate
+CMake in an alternate mode of :command:`file(INSTALL)` and :command:`install()`.
+
+The default behavior for an installation is to copy a source file from a
+source directory into a destination directory. This environment variable
+however allows the user to override this behavior, causing CMake to create
+symbolic links instead.
+
+.. note::
+ A symbolic link consists of a reference file path rather than contents of its own,
+ hence there are two ways to express the relation, either by a relative or an absolute path.
+
+The following values are allowed for ``CMAKE_INSTALL_MODE``:
+
+* empty, unset or ``COPY``: default behavior, duplicate the file at its destination
+* ``ABS_SYMLINK``: create an *absolute* symbolic link to the source file at the destination *or fail*
+* ``ABS_SYMLINK_OR_COPY``: like ``ABS_SYMLINK`` but silently copy on error
+* ``REL_SYMLINK``: create an *relative* symbolic link to the source file at the destination *or fail*
+* ``REL_SYMLINK_OR_COPY``: like ``REL_SYMLINK`` but silently copy on error
+* ``SYMLINK``: try as if through ``REL_SYMLINK`` and fall back to ``ABS_SYMLINK`` if the referenced
+ file cannot be expressed using a relative path. Fail on error.
+* ``SYMLINK_OR_COPY``: like ``SYMLINK`` but silently copy on error
+
+Installing symbolic links rather than copying files can help conserve storage space because files do
+not have to be duplicated on disk. However, modifications applied to the source immediately affects
+the symbolic link and vice versa. *Use with caution*.
+
+.. note:: ``CMAKE_INSTALL_MODE`` only affects files, *not* directories.
+
+.. note:: Symbolic links are not available on all platforms.
diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst
index c06555036..9ec33c354 100644
--- a/Help/generator/Visual Studio 10 2010.rst
+++ b/Help/generator/Visual Studio 10 2010.rst
@@ -1,7 +1,14 @@
Visual Studio 10 2010
---------------------
-Generates Visual Studio 10 (VS 2010) project files.
+Deprecated. Generates Visual Studio 10 (VS 2010) project files.
+
+.. note::
+ This generator is deprecated and will be removed in a future version
+ of CMake. It will still be possible to build with VS 10 2010 tools
+ using the :generator:`Visual Studio 11 2012` (or above) generator
+ with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v100``, or by
+ using the :generator:`NMake Makefiles` generator.
For compatibility with CMake versions prior to 3.0, one may specify this
generator using the name ``Visual Studio 10`` without the year component.
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index a4f5f98e3..b4d6f6d9f 100644
--- a/Help/generator/Visual Studio 15 2017.rst
+++ b/Help/generator/Visual Studio 15 2017.rst
@@ -15,20 +15,20 @@ Powershell, Python, etc.) are not supported.
Instance Selection
^^^^^^^^^^^^^^^^^^
-.. versionadded:: 3.9
- VS 2017 supports multiple installations on the same machine.
- The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
- cache entry containing the absolute path to a Visual Studio instance.
- If the value is not specified explicitly by the user or a toolchain file,
- CMake queries the Visual Studio Installer to locate VS instances, chooses
- one, and sets the variable as a cache entry to hold the value persistently.
-
.. versionadded:: 3.11
- When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment
- variable is set and points to the ``Common7/Tools`` directory within
- one of the instances, that instance will be used. Otherwise, if more
- than one instance is installed we do not define which one is chosen
- by default.
+
+VS 2017 supports multiple installations on the same machine.
+The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
+cache entry containing the absolute path to a Visual Studio instance.
+If the value is not specified explicitly by the user or a toolchain file,
+CMake queries the Visual Studio Installer to locate VS instances, chooses
+one, and sets the variable as a cache entry to hold the value persistently.
+
+When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment
+variable is set and points to the ``Common7/Tools`` directory within
+one of the instances, that instance will be used. Otherwise, if more
+than one instance is installed we do not define which one is chosen
+by default.
Platform Selection
^^^^^^^^^^^^^^^^^^
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst
index 41e8479b2..cf1ec0186 100644
--- a/Help/guide/tutorial/A Basic Starting Point.rst
+++ b/Help/guide/tutorial/A Basic Starting Point.rst
@@ -24,6 +24,45 @@ Upper, lower, and mixed case commands are supported by CMake. The source
code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be
used to compute the square root of a number.
+Build and Run
+-------------
+
+That's all that is needed - we can build and run our project now! First, run
+the :manual:`cmake <cmake(1)>` executable or the
+:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
+with your chosen build tool.
+
+For example, from the command line we could navigate to the
+``Help/guide/tutorial`` directory of the CMake source code tree and create a
+build directory:
+
+.. code-block:: console
+
+ mkdir Step1_build
+
+Next, navigate to the build directory and run CMake to configure the project
+and generate a native build system:
+
+.. code-block:: console
+
+ cd Step1_build
+ cmake ../Step1
+
+Then call that build system to actually compile/link the project:
+
+.. code-block:: console
+
+ cmake --build .
+
+Finally, try to use the newly built ``Tutorial`` with these commands:
+
+.. code-block:: console
+
+ Tutorial 4294967296
+ Tutorial 10
+ Tutorial
+
+
Adding a Version Number and Configured Header File
--------------------------------------------------
@@ -113,39 +152,24 @@ call to ``add_executable``.
:language: cmake
:end-before: # configure a header file to pass some of the CMake settings
-Build and Test
---------------
-
-Run the :manual:`cmake <cmake(1)>` executable or the
-:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it
-with your chosen build tool.
-
-For example, from the command line we could navigate to the
-``Help/guide/tutorial`` directory of the CMake source code tree and create a
-build directory:
-
-.. code-block:: console
+Rebuild
+-------
- mkdir Step1_build
-
-Next, navigate to the build directory and run CMake to configure the project
-and generate a native build system:
+Let's build our project again. We already created a build directory and ran
+CMake, so we can skip to the build step:
.. code-block:: console
cd Step1_build
- cmake ../Step1
-
-Then call that build system to actually compile/link the project:
-
-.. code-block:: console
-
cmake --build .
-Finally, try to use the newly built ``Tutorial`` with these commands:
+Now we can try to use the newly built ``Tutorial`` with same commands as before:
.. code-block:: console
Tutorial 4294967296
Tutorial 10
Tutorial
+
+Check that the version number is now reported when running the executable without
+any arguments.
diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst
index e5ab6a226..3bd6d6464 100644
--- a/Help/guide/tutorial/Adding Export Configuration.rst
+++ b/Help/guide/tutorial/Adding Export Configuration.rst
@@ -12,10 +12,10 @@ packaged.
The first step is to update our :command:`install(TARGETS)` commands to not
only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
-generates and installs a CMake file containing code to import all targets
-listed in the install command from the installation tree. So let's go ahead and
-explicitly ``EXPORT`` the ``MathFunctions`` library by updating the ``install``
-command in ``MathFunctions/CMakeLists.txt`` to look like:
+generates a CMake file containing code to import all targets listed in the
+install command from the installation tree. So let's go ahead and explicitly
+``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command
+in ``MathFunctions/CMakeLists.txt`` to look like:
.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
@@ -82,6 +82,46 @@ bottom of the top-level ``CMakeLists.txt``:
:name: CMakeLists.txt-install-Config.cmake
:language: cmake
:start-after: # install the configuration targets
+ :end-before: # generate the config file
+
+
+Next, we execute the :command:`configure_package_config_file`. This command
+will configure a provided file but with a few specific differences from the
+standard :command:`configure_file` way.
+To properly utilize this function, the input file should have a single line
+with the text ``@PACKAGE_INIT@`` in addition to the content that is desired.
+That variable will be replaced with a block of code which turns set values into
+relative paths. These values which are new can be referenced by the same name
+but prepended with a ``PACKAGE_`` prefix.
+
+.. literalinclude:: Step12/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-configure-package-config.cmake
+ :language: cmake
+ :start-after: # install the configuration targets
+ :end-before: # generate the version file
+
+The :command:`write_basic_package_version_file` is next. This command writes
+a file which is used by the "find_package" document the version and
+compatibility of the desired package. Here, we use the ``Tutorial_VERSION_*``
+variables and say that it is compatible with ``AnyNewerVersion``, which
+denotes that this version or any higher one are compatible with the requested
+version.
+
+.. literalinclude:: Step12/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-basic-version-file.cmake
+ :language: cmake
+ :start-after: # generate the version file
+ :end-before: # install the generated configuration files
+
+Finally, set both generated files to be installed:
+
+.. literalinclude:: Step12/CMakeLists.txt
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-install-configured-files.cmake
+ :language: cmake
+ :start-after: # install the generated configuration files
:end-before: # generate the export
At this point, we have generated a relocatable CMake Configuration for our
diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst
index 55acb346f..7fcc97fcc 100644
--- a/Help/guide/tutorial/Adding Generator Expressions.rst
+++ b/Help/guide/tutorial/Adding Generator Expressions.rst
@@ -53,6 +53,16 @@ Would be replaced with:
:start-after: project(Tutorial VERSION 1.0)
:end-before: # add compiler warning flags just when building this project via
+**Note**: This upcoming section will require a change to the
+:command:`cmake_minimum_required` usage in the code. The Generator Expression
+that is about to be used was introduced in `3.15`. Update the call to require
+that more recent version:
+
+.. code-block:: cmake
+ :caption: CMakeLists.txt
+ :name: CMakeLists.txt-version-update
+
+ cmake_minimum_required(VERSION 3.15)
Next we add the desired compiler warning flags that we want for our project. As
warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID``
diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
index 26aae4f81..c6e0fd0b3 100644
--- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
+++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
@@ -28,9 +28,23 @@ With:
The :module:`CTest` module will automatically call ``enable_testing()``, so we
can remove it from our CMake files.
-We will also need to create a ``CTestConfig.cmake`` file in the top-level
-directory where we can specify the name of the project and where to submit the
-dashboard.
+We will also need to acquire a ``CTestConfig.cmake`` file to be placed in the
+top-level directory where we can specify information to CTest about the
+project. It contains:
+
+* The project name
+
+* The project "Nightly" start time
+
+ * The time when a 24 hour "day" starts for this project.
+
+* The URL of the CDash instance where the submission's generated documents
+ will be sent
+
+One has been provided for you in this directory. It would normally be
+downloaded from the ``Settings`` page of the project on the CDash
+instance that will host and display the test results. Once downloaded from
+CDash, the file should not be modified locally.
.. literalinclude:: Step9/CTestConfig.cmake
:caption: CTestConfig.cmake
diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst
index 7210a8dbc..e14911008 100644
--- a/Help/guide/tutorial/Adding System Introspection.rst
+++ b/Help/guide/tutorial/Adding System Introspection.rst
@@ -14,11 +14,14 @@ these functions using the :module:`CheckSymbolExists` module in
the ``m`` library. If ``log`` and ``exp`` are not initially found, require the
``m`` library and try again.
+Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``,
+after the call to :command:`target_include_directories`:
+
.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-check_symbol_exists
:language: cmake
- :start-after: # does this system provide the log and exp functions?
+ :start-after: # to find MathFunctions.h, while we don't.
:end-before: # add compile definitions
If available, use :command:`target_compile_definitions` to specify
diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst
index 180636141..ed034489c 100644
--- a/Help/guide/tutorial/Adding a Library.rst
+++ b/Help/guide/tutorial/Adding a Library.rst
@@ -64,8 +64,13 @@ will be stored in the cache so that the user does not need to set the value
each time they run CMake on a build directory.
The next change is to make building and linking the ``MathFunctions`` library
-conditional. To do this we change the end of the top-level ``CMakeLists.txt``
-file to look like the following:
+conditional. To do this, we will create an ``if`` statement which checks the
+value of the option. Inside the ``if`` block, put the
+:command:`add_subdirectory` command from above with some additional list
+commands to store information needed to link to the library and add the
+subdirectory as an include directory in the ``Tutorial`` target.
+The end of the top-level ``CMakeLists.txt`` file will now look like the
+following:
.. literalinclude:: Step3/CMakeLists.txt
:caption: CMakeLists.txt
diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt
index 4d8a3ada8..ac1d0839a 100644
--- a/Help/guide/tutorial/Complete/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/CMakeLists.txt
@@ -73,7 +73,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -81,7 +81,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst
index 2fc3202e5..394c9865f 100644
--- a/Help/guide/tutorial/Installing and Testing.rst
+++ b/Help/guide/tutorial/Installing and Testing.rst
@@ -88,6 +88,8 @@ input, and expected results based on the passed arguments.
Rebuild the application and then cd to the binary directory and run the
:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For
multi-config generators (e.g. Visual Studio), the configuration type must be
-specified. To run tests in Debug mode, for example, use ``ctest -C Debug -VV``
-from the build directory (not the Debug subdirectory!). Alternatively, build
-the ``RUN_TESTS`` target from the IDE.
+specified with the ``-C <mode>`` flag. For example, to run tests in Debug
+mode use ``ctest -C Debug -VV`` from the binary directory
+(not the Debug subdirectory!). Release mode would be executed from the same
+location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS``
+target from the IDE.
diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt
index 34ae70c27..dc9a0e8e6 100644
--- a/Help/guide/tutorial/Step10/CMakeLists.txt
+++ b/Help/guide/tutorial/Step10/CMakeLists.txt
@@ -55,7 +55,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -63,7 +63,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt
index 4763951c7..10f35ce2d 100644
--- a/Help/guide/tutorial/Step11/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/CMakeLists.txt
@@ -63,7 +63,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -71,7 +71,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt
index 1b0c82667..634b84cdd 100644
--- a/Help/guide/tutorial/Step12/CMakeLists.txt
+++ b/Help/guide/tutorial/Step12/CMakeLists.txt
@@ -69,7 +69,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -77,7 +77,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
@@ -107,7 +107,7 @@ write_basic_package_version_file(
COMPATIBILITY AnyNewerVersion
)
-# install the configuration file
+# install the generated configuration files
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt
index c3b375a3d..82d00c8d4 100644
--- a/Help/guide/tutorial/Step5/CMakeLists.txt
+++ b/Help/guide/tutorial/Step5/CMakeLists.txt
@@ -54,7 +54,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt
index c3b375a3d..82d00c8d4 100644
--- a/Help/guide/tutorial/Step6/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/CMakeLists.txt
@@ -54,7 +54,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt
index c3b375a3d..82d00c8d4 100644
--- a/Help/guide/tutorial/Step7/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/CMakeLists.txt
@@ -54,7 +54,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -62,5 +62,5 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt
index 19b9913e9..4ae898f9b 100644
--- a/Help/guide/tutorial/Step8/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/CMakeLists.txt
@@ -54,7 +54,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -62,7 +62,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
# setup installer
diff --git a/Help/guide/tutorial/Step8/CTestConfig.cmake b/Help/guide/tutorial/Step8/CTestConfig.cmake
new file mode 100644
index 000000000..73efdb1f6
--- /dev/null
+++ b/Help/guide/tutorial/Step8/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt
index d5f1cc897..130bc9a20 100644
--- a/Help/guide/tutorial/Step9/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/CMakeLists.txt
@@ -54,7 +54,7 @@ function(do_test target arg result)
set_tests_properties(Comp${arg}
PROPERTIES PASS_REGULAR_EXPRESSION ${result}
)
-endfunction(do_test)
+endfunction()
# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
@@ -62,7 +62,7 @@ do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
-do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
include(InstallRequiredSystemLibraries)
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index 70083833d..2f430705e 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -21,9 +21,9 @@ Binary Targets
Executables and libraries are defined using the :command:`add_executable`
and :command:`add_library` commands. The resulting binary files have
-appropriate :prop_tgt:`PREFIX`, :prop_tgt:`SUFFIX` and extensions for the platform targeted.
-Dependencies between binary targets are expressed using the
-:command:`target_link_libraries` command:
+appropriate :prop_tgt:`PREFIX`, :prop_tgt:`SUFFIX` and extensions for the
+platform targeted. Dependencies between binary targets are expressed using
+the :command:`target_link_libraries` command:
.. code-block:: cmake
@@ -530,38 +530,6 @@ the calculated "compatible" value of a property may be read with the
In this case, the ``exe1`` source files will be compiled with
``-DCONTAINER_SIZE=200``.
-Configuration determined build specifications may be conveniently set using
-the ``CONFIG`` generator expression.
-
-.. code-block:: cmake
-
- target_compile_definitions(exe1 PRIVATE
- $<$<CONFIG:Debug>:DEBUG_BUILD>
- )
-
-The ``CONFIG`` parameter is compared case-insensitively with the configuration
-being built. In the presence of :prop_tgt:`IMPORTED` targets, the content of
-:prop_tgt:`MAP_IMPORTED_CONFIG_DEBUG <MAP_IMPORTED_CONFIG_<CONFIG>>` is also
-accounted for by this expression.
-
-Some buildsystems generated by :manual:`cmake(1)` have a predetermined
-build-configuration set in the :variable:`CMAKE_BUILD_TYPE` variable. The
-buildsystem for the IDEs such as Visual Studio and Xcode are generated
-independent of the build-configuration, and the actual build configuration
-is not known until build-time. Therefore, code such as
-
-.. code-block:: cmake
-
- string(TOLOWER ${CMAKE_BUILD_TYPE} _type)
- if (_type STREQUAL debug)
- target_compile_definitions(exe1 PRIVATE DEBUG_BUILD)
- endif()
-
-may appear to work for :ref:`Makefile Generators` and :generator:`Ninja`
-generators, but is not portable to IDE generators. Additionally,
-the :prop_tgt:`IMPORTED` configuration-mappings are not accounted for
-with code like this, so it should be avoided.
-
The unary ``TARGET_PROPERTY`` generator expression and the ``TARGET_POLICY``
generator expression are evaluated with the consuming target context. This
means that a usage requirement specification may be evaluated differently based
@@ -840,6 +808,121 @@ target at a time. The commands :command:`add_compile_definitions`,
a similar function, but operate at directory scope instead of target
scope for convenience.
+.. _`Build Configurations`:
+
+Build Configurations
+====================
+
+Configurations determine specifications for a certain type of build, such
+as ``Release`` or ``Debug``. The way this is specified depends on the type
+of :manual:`generator <cmake-generators(7)>` being used. For single
+configuration generators like :ref:`Makefile Generators` and
+:generator:`Ninja`, the configuration is specified at configure time by the
+:variable:`CMAKE_BUILD_TYPE` variable. For multi-configuration generators
+like :ref:`Visual Studio <Visual Studio Generators>`, :generator:`Xcode`, and
+:generator:`Ninja Multi-Config`, the configuration is chosen by the user at
+build time and :variable:`CMAKE_BUILD_TYPE` is ignored. In the
+multi-configuration case, the set of *available* configurations is specified
+at configure time by the :variable:`CMAKE_CONFIGURATION_TYPES` variable,
+but the actual configuration used cannot be known until the build stage.
+This difference is often misunderstood, leading to problematic code like the
+following:
+
+.. code-block:: cmake
+
+ # WARNING: This is wrong for multi-config generators because they don't use
+ # and typically don't even set CMAKE_BUILD_TYPE
+ string(TOLOWER ${CMAKE_BUILD_TYPE} build_type)
+ if (build_type STREQUAL debug)
+ target_compile_definitions(exe1 PRIVATE DEBUG_BUILD)
+ endif()
+
+:manual:`Generator expressions <cmake-generator-expressions(7)>` should be
+used instead to handle configuration-specific logic correctly, regardless of
+the generator used. For example:
+
+.. code-block:: cmake
+
+ # Works correctly for both single and multi-config generators
+ target_compile_definitions(exe1 PRIVATE
+ $<$<CONFIG:Debug>:DEBUG_BUILD>
+ )
+
+In the presence of :prop_tgt:`IMPORTED` targets, the content of
+:prop_tgt:`MAP_IMPORTED_CONFIG_DEBUG <MAP_IMPORTED_CONFIG_<CONFIG>>` is also
+accounted for by the above ``$<CONFIG:Debug>`` expression.
+
+
+Case Sensitivity
+----------------
+
+:variable:`CMAKE_BUILD_TYPE` and :variable:`CMAKE_CONFIGURATION_TYPES` are
+just like other variables in that any string comparisons made with their
+values will be case-sensitive. The ``$<CONFIG>`` generator expression also
+preserves the casing of the configuration as set by the user or CMake defaults.
+For example:
+
+.. code-block:: cmake
+
+ # NOTE: Don't use these patterns, they are for illustration purposes only.
+
+ set(CMAKE_BUILD_TYPE Debug)
+ if(CMAKE_BUILD_TYPE STREQUAL DEBUG)
+ # ... will never get here, "Debug" != "DEBUG"
+ endif()
+ add_custom_target(print_config ALL
+ # Prints "Config is Debug" in this single-config case
+ COMMAND ${CMAKE_COMMAND} -E echo "Config is $<CONFIG>"
+ VERBATIM
+ )
+
+ set(CMAKE_CONFIGURATION_TYPES Debug Release)
+ if(DEBUG IN_LIST CMAKE_CONFIGURATION_TYPES)
+ # ... will never get here, "Debug" != "DEBUG"
+ endif()
+
+In contrast, CMake treats the configuration type case-insensitively when
+using it internally in places that modify behavior based on the configuration.
+For example, the ``$<CONFIG:Debug>`` generator expression will evaluate to 1
+for a configuration of not only ``Debug``, but also ``DEBUG``, ``debug`` or
+even ``DeBuG``. Therefore, you can specify configuration types in
+:variable:`CMAKE_BUILD_TYPE` and :variable:`CMAKE_CONFIGURATION_TYPES` with
+any mixture of upper and lowercase, although there are strong conventions
+(see the next section). If you must test the value in string comparisons,
+always convert the value to upper or lowercase first and adjust the test
+accordingly.
+
+Default And Custom Configurations
+---------------------------------
+
+By default, CMake defines a number of standard configurations:
+
+* ``Debug``
+* ``Release``
+* ``RelWithDebInfo``
+* ``MinSizeRel``
+
+In multi-config generators, the :variable:`CMAKE_CONFIGURATION_TYPES` variable
+will be populated with (potentially a subset of) the above list by default,
+unless overridden by the project or user. The actual configuration used is
+selected by the user at build time.
+
+For single-config generators, the configuration is specified with the
+:variable:`CMAKE_BUILD_TYPE` variable at configure time and cannot be changed
+at build time. The default value will often be none of the above standard
+configurations and will instead be an empty string. A common misunderstanding
+is that this is the same as ``Debug``, but that is not the case. Users should
+always explicitly specify the build type instead to avoid this common problem.
+
+The above standard configuration types provide reasonable behavior on most
+platforms, but they can be extended to provide other types. Each configuration
+defines a set of compiler and linker flag variables for the language in use.
+These variables follow the convention :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`,
+where ``<CONFIG>`` is always the uppercase configuration name. When defining
+a custom configuration type, make sure these variables are set appropriately,
+typically as cache variables.
+
+
Pseudo Targets
==============
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst
index 2b0de1101..67b0f6ec7 100644
--- a/Help/manual/cmake-compile-features.7.rst
+++ b/Help/manual/cmake-compile-features.7.rst
@@ -118,13 +118,12 @@ as well as any dependents (that may include headers from ``mylib``).
Availability of Compiler Extensions
-----------------------------------
-Because the :prop_tgt:`CXX_EXTENSIONS` target property is ``ON`` by default,
-CMake uses extended variants of language dialects by default, such as
-``-std=gnu++11`` instead of ``-std=c++11``. That target property may be
-set to ``OFF`` to use the non-extended variant of the dialect flag. Note
-that because most compilers enable extensions by default, this could
-expose cross-platform bugs in user code or in the headers of third-party
-dependencies.
+The :prop_tgt:`<LANG>_EXTENSIONS` target property defaults to the compiler's
+default (see :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`). Note that because
+most compilers enable extensions by default, this may expose portability bugs
+in user code or in the headers of third-party dependencies.
+
+:prop_tgt:`<LANG>_EXTENSIONS` used to default to ``ON``. See :policy:`CMP0128`.
Optional Compile Features
=========================
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index fa38588a8..0799fddb6 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -30,12 +30,15 @@ Environment Variables that Control the Build
/envvar/CMAKE_APPLE_SILICON_PROCESSOR
/envvar/CMAKE_BUILD_PARALLEL_LEVEL
+ /envvar/CMAKE_BUILD_TYPE
+ /envvar/CMAKE_CONFIGURATION_TYPES
/envvar/CMAKE_CONFIG_TYPE
/envvar/CMAKE_EXPORT_COMPILE_COMMANDS
/envvar/CMAKE_GENERATOR
/envvar/CMAKE_GENERATOR_INSTANCE
/envvar/CMAKE_GENERATOR_PLATFORM
/envvar/CMAKE_GENERATOR_TOOLSET
+ /envvar/CMAKE_INSTALL_MODE
/envvar/CMAKE_LANG_COMPILER_LAUNCHER
/envvar/CMAKE_LANG_LINKER_LAUNCHER
/envvar/CMAKE_MSVCIDE_RUN_PATH
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index d3cbd491c..df13dd0ae 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -134,8 +134,8 @@ Variable Queries
.. genex:: $<CONFIG:cfgs>
- ``1`` if config is any one of the entries in ``cfgs``, else ``0``. This is a
- case-insensitive comparison. The mapping in
+ ``1`` if config is any one of the entries in comma-separated list
+ ``cfgs``, else ``0``. This is a case-insensitive comparison. The mapping in
:prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by this
expression when it is evaluated on a property on an :prop_tgt:`IMPORTED`
target.
diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst
index 4b2934a8e..5c109ff67 100644
--- a/Help/manual/cmake-packages.7.rst
+++ b/Help/manual/cmake-packages.7.rst
@@ -74,7 +74,9 @@ package.
By setting the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable to
``TRUE``, the ``<PackageName>`` package will not be searched, and will always
-be ``NOTFOUND``.
+be ``NOTFOUND``. Likewise, setting the
+:variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` to ``TRUE`` will make the
+package REQUIRED.
.. _`Config File Packages`:
@@ -447,7 +449,7 @@ be true. This can be tested with logic in the package configuration file:
set(_supported_components Plot Table)
foreach(_comp ${ClimbingStats_FIND_COMPONENTS})
- if (NOT ";${_supported_components};" MATCHES _comp)
+ if (NOT ";${_supported_components};" MATCHES ";${_comp};")
set(ClimbingStats_FOUND False)
set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
endif()
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index b9e3d452f..3df4f9fa7 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,15 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.22
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0128: Selection of language standard and extension flags improved. </policy/CMP0128>
+ CMP0127: cmake_dependent_option() supports full Condition Syntax. </policy/CMP0127>
+
Policies Introduced by CMake 3.21
=================================
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 5f18a8247..bb5dba3f0 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -202,6 +202,7 @@ Properties on Targets
/prop_tgt/EXPORT_NAME
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
+ /prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES
/prop_tgt/Fortran_FORMAT
/prop_tgt/Fortran_MODULE_DIRECTORY
/prop_tgt/Fortran_PREPROCESS
@@ -214,6 +215,9 @@ Properties on Targets
/prop_tgt/GNUtoMS
/prop_tgt/HAS_CXX
/prop_tgt/HIP_ARCHITECTURES
+ /prop_tgt/HIP_EXTENSIONS
+ /prop_tgt/HIP_STANDARD
+ /prop_tgt/HIP_STANDARD_REQUIRED
/prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
/prop_tgt/IMPORTED
/prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME
@@ -273,8 +277,11 @@ Properties on Targets
/prop_tgt/LANG_COMPILER_LAUNCHER
/prop_tgt/LANG_CPPCHECK
/prop_tgt/LANG_CPPLINT
+ /prop_tgt/LANG_EXTENSIONS
/prop_tgt/LANG_INCLUDE_WHAT_YOU_USE
/prop_tgt/LANG_LINKER_LAUNCHER
+ /prop_tgt/LANG_STANDARD
+ /prop_tgt/LANG_STANDARD_REQUIRED
/prop_tgt/LANG_VISIBILITY_PRESET
/prop_tgt/LIBRARY_OUTPUT_DIRECTORY
/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG
@@ -450,6 +457,7 @@ Properties on Tests
/prop_test/DEPENDS
/prop_test/DISABLED
/prop_test/ENVIRONMENT
+ /prop_test/ENVIRONMENT_MODIFICATION
/prop_test/FAIL_REGULAR_EXPRESSION
/prop_test/FIXTURES_CLEANUP
/prop_test/FIXTURES_REQUIRED
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 9cea0fbc1..4ed0b2e62 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -71,6 +71,7 @@ Variables that Provide Information
/variable/CMAKE_JOB_POOL_PRECOMPILE_HEADER
/variable/CMAKE_JOB_POOLS
/variable/CMAKE_LANG_COMPILER_AR
+ /variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT
/variable/CMAKE_LANG_COMPILER_RANLIB
/variable/CMAKE_LANG_LINK_LIBRARY_SUFFIX
/variable/CMAKE_LINK_LIBRARY_SUFFIX
@@ -124,6 +125,9 @@ Variables that Provide Information
/variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
/variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
+ /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION
+ /variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
+ /variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
/variable/CMAKE_XCODE_BUILD_SYSTEM
@@ -231,6 +235,7 @@ Variables that Change Behavior
/variable/CMAKE_PROJECT_INCLUDE_BEFORE
/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE
/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE
+ /variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName
/variable/CMAKE_SKIP_INSTALL_ALL_DEPENDENCY
/variable/CMAKE_STAGING_PREFIX
/variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
@@ -246,6 +251,7 @@ Variables that Change Behavior
/variable/CMAKE_SYSTEM_LIBRARY_PATH
/variable/CMAKE_SYSTEM_PREFIX_PATH
/variable/CMAKE_SYSTEM_PROGRAM_PATH
+ /variable/CMAKE_TLS_CAINFO
/variable/CMAKE_TLS_VERIFY
/variable/CMAKE_USER_MAKE_RULES_OVERRIDE
/variable/CMAKE_WARN_DEPRECATED
@@ -428,6 +434,7 @@ Variables that Control the Build
/variable/CMAKE_LANG_LINKER_LAUNCHER
/variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LANG_LINK_LIBRARY_FLAG
+ /variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG
/variable/CMAKE_LANG_VISIBILITY_PRESET
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG
@@ -438,6 +445,7 @@ Variables that Control the Build
/variable/CMAKE_LINK_LIBRARY_FILE_FLAG
/variable/CMAKE_LINK_LIBRARY_FLAG
/variable/CMAKE_LINK_WHAT_YOU_USE
+ /variable/CMAKE_LINK_WHAT_YOU_USE_CHECK
/variable/CMAKE_MACOSX_BUNDLE
/variable/CMAKE_MACOSX_RPATH
/variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
@@ -525,6 +533,9 @@ Variables for Languages
/variable/CMAKE_Fortran_MODDIR_FLAG
/variable/CMAKE_Fortran_MODOUT_FLAG
/variable/CMAKE_HIP_ARCHITECTURES
+ /variable/CMAKE_HIP_EXTENSIONS
+ /variable/CMAKE_HIP_STANDARD
+ /variable/CMAKE_HIP_STANDARD_REQUIRED
/variable/CMAKE_ISPC_HEADER_DIRECTORY
/variable/CMAKE_ISPC_HEADER_SUFFIX
/variable/CMAKE_ISPC_INSTRUCTION_SETS
@@ -546,6 +557,8 @@ Variables for Languages
/variable/CMAKE_LANG_CREATE_SHARED_LIBRARY
/variable/CMAKE_LANG_CREATE_SHARED_MODULE
/variable/CMAKE_LANG_CREATE_STATIC_LIBRARY
+ /variable/CMAKE_LANG_EXTENSIONS
+ /variable/CMAKE_LANG_EXTENSIONS_DEFAULT
/variable/CMAKE_LANG_FLAGS
/variable/CMAKE_LANG_FLAGS_CONFIG
/variable/CMAKE_LANG_FLAGS_CONFIG_INIT
@@ -574,8 +587,11 @@ Variables for Languages
/variable/CMAKE_LANG_SIMULATE_VERSION
/variable/CMAKE_LANG_SIZEOF_DATA_PTR
/variable/CMAKE_LANG_SOURCE_FILE_EXTENSIONS
+ /variable/CMAKE_LANG_STANDARD
+ /variable/CMAKE_LANG_STANDARD_DEFAULT
/variable/CMAKE_LANG_STANDARD_INCLUDE_DIRECTORIES
/variable/CMAKE_LANG_STANDARD_LIBRARIES
+ /variable/CMAKE_LANG_STANDARD_REQUIRED
/variable/CMAKE_OBJC_EXTENSIONS
/variable/CMAKE_OBJC_STANDARD
/variable/CMAKE_OBJC_STANDARD_REQUIRED
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 03d8bf6c8..d66c5a9d5 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -464,6 +464,10 @@ CTest prints timing summary information for each ``LABEL`` and subproject
associated with the tests run. The label time summary will not include labels
that are mapped to subprojects.
+.. versionadded:: 3.22
+ Labels added dynamically during test execution are also reported in the
+ timing summary. See :ref:`Additional Labels`.
+
When the :prop_test:`PROCESSORS` test property is set, CTest will display a
weighted test timing result in label and subproject summaries. The time is
reported with `sec*proc` instead of just `sec`.
diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json
index 767e80b6b..7852550dc 100644
--- a/Help/manual/presets/schema.json
+++ b/Help/manual/presets/schema.json
@@ -124,7 +124,7 @@
},
{
"type": "array",
- "description": "An optional array of strings representing the names of presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "description": "An optional array of strings representing the names of presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
"items": {
"type": "string",
"description": "An optional string representing the name of the preset to inherit from.",
@@ -446,7 +446,7 @@
},
{
"type": "array",
- "description": "An optional array of strings representing the names of build presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "description": "An optional array of strings representing the names of build presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
"items": {
"type": "string",
"description": "An optional string representing the name of the preset to inherit from.",
@@ -641,7 +641,7 @@
},
{
"type": "array",
- "description": "An optional array of strings representing the names of test presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json may not inherit from presets in CMakeUserPresets.json.",
+ "description": "An optional array of strings representing the names of test presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.",
"items": {
"type": "string",
"description": "An optional string representing the name of the preset to inherit from.",
diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst
new file mode 100644
index 000000000..2106110d4
--- /dev/null
+++ b/Help/policy/CMP0127.rst
@@ -0,0 +1,34 @@
+CMP0127
+-------
+
+.. versionadded:: 3.22
+
+:command:`cmake_dependent_option` supports full :ref:`Condition Syntax`.
+
+The ``<depends>`` parameter accepts a :ref:`semicolon-separated list <CMake
+Language Lists>` of conditions. CMake 3.21 and lower evaluates each
+``condition`` as ``if(${condition})``, which does not properly handle
+conditions with nested paren groups. CMake 3.22 and above instead prefer
+to evaluate each ``condition`` as ``if(<condition>)``, where ``<condition>``
+is re-parsed as if literally written in a call to :command:`if`. This
+allows expressions like::
+
+ "A AND (B OR C)"
+
+but requires expressions like::
+
+ "FOO MATCHES (UPPER|lower)"
+
+to be re-written as::
+
+ "FOO MATCHES \"(UPPER|lower)\""
+
+Policy ``CMP0127`` provides compatibility for projects that have not
+been updated to expect the new behavior.
+
+This policy was introduced in CMake version 3.22. CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0128.rst b/Help/policy/CMP0128.rst
new file mode 100644
index 000000000..604a146a1
--- /dev/null
+++ b/Help/policy/CMP0128.rst
@@ -0,0 +1,71 @@
+CMP0128
+-------
+
+.. versionadded:: 3.22
+
+When this policy is set to ``NEW``:
+
+* :prop_tgt:`<LANG>_EXTENSIONS` is initialized to
+ :variable:`CMAKE_<LANG>_EXTENSIONS` if set, otherwise falling back to
+ :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`.
+
+* Extensions are correctly enabled/disabled if :prop_tgt:`<LANG>_STANDARD` is
+ unset or satisfied by the default.
+
+* Standard mode-affecting flags aren't added unless necessary to achieve the
+ specified mode.
+
+The ``OLD`` behavior:
+
+* Initializes :prop_tgt:`<LANG>_EXTENSIONS` to
+ :variable:`CMAKE_<LANG>_EXTENSIONS` if set, otherwise falling back to ``ON``.
+
+* Always adds a flag if :prop_tgt:`<LANG>_STANDARD` is set and
+ :prop_tgt:`<LANG>_STANDARD_REQUIRED` is ``OFF``.
+
+* If :prop_tgt:`<LANG>_STANDARD` is unset:
+
+ * Doesn't disable extensions even if :prop_tgt:`<LANG>_EXTENSIONS` is
+ ``OFF``.
+
+ * Fails to enable extensions if :prop_tgt:`<LANG>_EXTENSIONS` is ``ON``
+ except for the ``IAR`` compiler.
+
+Code may need to be updated for the ``NEW`` behavior in the following cases:
+
+* If a standard mode flag previously overridden by CMake's and not used during
+ compiler detection now takes effect due to CMake no longer adding one as the
+ default detected is appropriate.
+
+ Such code should be converted to either:
+
+ * Use :prop_tgt:`<LANG>_STANDARD` and :prop_tgt:`<LANG>_EXTENSIONS` instead
+ of manually adding flags.
+
+ * Or ensure the manually-specified flags are used during compiler detection.
+
+* If extensions were disabled without :prop_tgt:`<LANG>_STANDARD` being set
+ CMake previously wouldn't actually disable extensions.
+
+ Such code should be updated to not disable extensions if they are required.
+
+* If extensions were enabled/disabled when :prop_tgt:`<LANG>_STANDARD` was
+ satisfied by the compiler's default CMake previously wouldn't actually
+ enable/disable extensions.
+
+ Such code should be updated to set the correct extensions mode.
+
+If compiler flags affecting the standard mode are used during compiler
+detection (for example in :manual:`a toolchain file <cmake-toolchains(7)>`
+using :variable:`CMAKE_<LANG>_FLAGS_INIT`) then they will affect the detected
+default :variable:`standard <CMAKE_<LANG>_STANDARD_DEFAULT>` and
+:variable:`extensions <CMAKE_<LANG>_EXTENSIONS_DEFAULT>`.
+
+Unlike many policies, CMake version |release| does *not* warn when the policy
+is not set and simply uses the ``OLD`` behavior. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+See documentation of the
+:variable:`CMAKE_POLICY_WARNING_CMP0128 <CMAKE_POLICY_WARNING_CMP<NNNN>>`
+variable to control the warning.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
index 6bbb870f1..3a1797356 100644
--- a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst
@@ -32,4 +32,6 @@ The features known to this version of CMake are:
Compiler mode is at least CUDA/C++ 20.
``cuda_std_23``
+ .. versionadded:: 3.20
+
Compiler mode is at least CUDA/C++ 23.
diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
index 73c0b34ee..1a913fb65 100644
--- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst
@@ -18,6 +18,8 @@ The features known to this version of CMake are listed below.
High level meta features indicating C++ standard support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 3.8
+
The following meta features indicate general support for the associated
language standard. It reflects the language support claimed by the compiler,
but it does not necessarily imply complete conformance to that standard.
@@ -35,9 +37,13 @@ but it does not necessarily imply complete conformance to that standard.
Compiler mode is at least C++ 17.
``cxx_std_20``
+ .. versionadded:: 3.12
+
Compiler mode is at least C++ 20.
``cxx_std_23``
+ .. versionadded:: 3.20
+
Compiler mode is at least C++ 23.
Low level individual compile features
diff --git a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
index 2bd0febea..97da697e0 100644
--- a/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
+++ b/Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst
@@ -13,7 +13,12 @@ The features listed here may be used with the :command:`target_compile_features`
command. See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
-The features known to this version of CMake are:
+The features known to this version of CMake are listed below.
+
+High level meta features indicating C standard support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.8
``c_std_90``
Compiler mode is at least C 90.
@@ -25,11 +30,18 @@ The features known to this version of CMake are:
Compiler mode is at least C 11.
``c_std_17``
+ .. versionadded:: 3.21
+
Compiler mode is at least C 17.
``c_std_23``
+ .. versionadded:: 3.21
+
Compiler mode is at least C 23.
+Low level individual compile features
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
``c_function_prototypes``
Function prototypes, as defined in ``ISO/IEC 9899:1990``.
diff --git a/Help/prop_sf/VS_SETTINGS.rst b/Help/prop_sf/VS_SETTINGS.rst
index 322f5a6d7..871e36e85 100644
--- a/Help/prop_sf/VS_SETTINGS.rst
+++ b/Help/prop_sf/VS_SETTINGS.rst
@@ -3,7 +3,12 @@ VS_SETTINGS
.. versionadded:: 3.18
-Set any item metadata on a non-built file.
+Set any item metadata on a file.
+
+.. versionadded:: 3.22
+
+ This property is honored for all source file types.
+ Previously it worked only for non-built files.
Takes a list of ``Key=Value`` pairs. Tells the Visual Studio generator to set
``Key`` to ``Value`` as item metadata on the file.
diff --git a/Help/prop_test/ENVIRONMENT.rst b/Help/prop_test/ENVIRONMENT.rst
index 102c7922f..43bcdbe1b 100644
--- a/Help/prop_test/ENVIRONMENT.rst
+++ b/Help/prop_test/ENVIRONMENT.rst
@@ -5,5 +5,5 @@ Specify environment variables that should be defined for running a test.
If set to a list of environment variables and values of the form
``MYVAR=value`` those environment variables will be defined while running
-the test. The environment is restored to its previous state after the
-test is done.
+the test. The environment changes from this property do not affect other
+tests.
diff --git a/Help/prop_test/ENVIRONMENT_MODIFICATION.rst b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst
new file mode 100644
index 000000000..0b3cd83a4
--- /dev/null
+++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst
@@ -0,0 +1,36 @@
+ENVIRONMENT_MODIFICATION
+------------------------
+
+.. versionadded:: 3.22
+
+Specify environment variables that should be modified for running a test. Note
+that the operations performed by this property are performed after the
+:prop_test:`ENVIRONMENT` property is already applied.
+
+If set to a list of environment variables and values of the form
+``MYVAR=OP:VALUE``, where ``MYVAR`` is the case-sensitive name of an
+environment variable to be modified. Entries are considered in the
+order specified in the property's value. The ``OP`` may be one of:
+
+ - ``reset``: Reset to the unmodified value, ignoring all modifications to
+ ``MYVAR`` prior to this entry. Note that this will reset the variable to
+ the value set by :prop_test:`ENVIRONMENT`, if it was set, and otherwise
+ to its state from the rest of the CTest execution.
+ - ``set``: Replaces the current value of ``MYVAR`` with ``VALUE``.
+ - ``unset``: Unsets the current value of ``MYVAR``.
+ - ``string_append``: Appends ``VALUE`` to the current value of ``MYVAR``.
+ - ``string_prepend``: Prepends ``VALUE`` to the current value of ``MYVAR``.
+ - ``path_list_append``: Appends ``VALUE`` to the current value of ``MYVAR``
+ using the platform-specific list separator.
+ - ``path_list_prepend``: Prepends ``VALUE`` to the current value of
+ ``MYVAR`` using the platform-specific list separator.
+ - ``cmake_list_append``: Appends ``VALUE`` to the current value of ``MYVAR``
+ using ``;`` as the separator.
+ - ``cmake_list_prepend``: Prepends ``VALUE`` to the current value of
+ ``MYVAR`` using ``;`` as the separator.
+
+Unrecognized ``OP`` values will result in the test failing before it is
+executed. This is so that future operations may be added without changing
+valid behavior of existing tests.
+
+The environment changes from this property do not affect other tests.
diff --git a/Help/prop_test/LABELS.rst b/Help/prop_test/LABELS.rst
index 8d7557095..a06f15274 100644
--- a/Help/prop_test/LABELS.rst
+++ b/Help/prop_test/LABELS.rst
@@ -1,6 +1,10 @@
LABELS
------
-Specify a list of text labels associated with a test.
+Specify a list of text labels associated with a test. The labels are
+reported in both the ``ctest`` output summary and in dashboard submissions.
+They can also be used to filter the set of tests to be executed (see the
+``ctest -L`` and ``ctest -LE`` :ref:`CTest Options`).
-The list is reported in dashboard submissions.
+See :ref:`Additional Labels` for adding labels to a test dynamically during
+test execution.
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index 52d96e02f..ed8b2626b 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -4,9 +4,9 @@ AUTOMOC
Should the target be processed with auto-moc (for Qt projects).
:prop_tgt:`AUTOMOC` is a boolean specifying whether CMake will handle the Qt
-``moc`` preprocessor automatically, i.e. without having to use the
-:module:`QT4_WRAP_CPP() <FindQt4>` or ``QT5_WRAP_CPP()`` macro.
-Currently Qt4 and Qt5 are supported.
+``moc`` preprocessor automatically, i.e. without having to use commands like
+:module:`QT4_WRAP_CPP() <FindQt4>`, ``QT5_WRAP_CPP()``, etc.
+Currently, Qt versions 4 to 6 are supported.
This property is initialized by the value of the :variable:`CMAKE_AUTOMOC`
variable if it is set when a target is created.
@@ -148,10 +148,13 @@ Qt version detection
:prop_tgt:`AUTOMOC` enabled targets need to know the Qt major and minor
version they're working with. The major version usually is provided by the
-``INTERFACE_QT_MAJOR_VERSION`` property of the ``Qt[45]Core`` library,
+``INTERFACE_QT_MAJOR_VERSION`` property of the ``Qt[456]Core`` library,
that the target links to. To find the minor version, CMake builds a list of
available Qt versions from
+- ``Qt6Core_VERSION_MAJOR`` and ``Qt6Core_VERSION_MINOR`` variables
+ (usually set by ``find_package(Qt6...)``)
+- ``Qt6Core_VERSION_MAJOR`` and ``Qt6Core_VERSION_MINOR`` directory properties
- ``Qt5Core_VERSION_MAJOR`` and ``Qt5Core_VERSION_MINOR`` variables
(usually set by ``find_package(Qt5...)``)
- ``Qt5Core_VERSION_MAJOR`` and ``Qt5Core_VERSION_MINOR`` directory properties
@@ -167,13 +170,13 @@ version was found, an error is generated.
If ``INTERFACE_QT_MAJOR_VERSION`` is not a valid number, the first
entry in the list is taken.
-A ``find_package(Qt[45]...)`` call sets the ``QT/Qt5Core_VERSION_MAJOR/MINOR``
+A ``find_package(Qt[456]...)`` call sets the ``QT/Qt[56]Core_VERSION_MAJOR/MINOR``
variables. If the call is in a different context than the
:command:`add_executable` or :command:`add_library` call, e.g. in a function,
then the version variables might not be available to the :prop_tgt:`AUTOMOC`
enabled target.
In that case the version variables can be forwarded from the
-``find_package(Qt[45]...)`` calling context to the :command:`add_executable`
+``find_package(Qt[456]...)`` calling context to the :command:`add_executable`
or :command:`add_library` calling context as directory properties.
The following Qt5 example demonstrates the procedure.
diff --git a/Help/prop_tgt/AUTORCC.rst b/Help/prop_tgt/AUTORCC.rst
index 9a98f440c..0a0c2a119 100644
--- a/Help/prop_tgt/AUTORCC.rst
+++ b/Help/prop_tgt/AUTORCC.rst
@@ -5,8 +5,8 @@ Should the target be processed with auto-rcc (for Qt projects).
:prop_tgt:`AUTORCC` is a boolean specifying whether CMake will handle
the Qt ``rcc`` code generator automatically, i.e. without having to use
-the :module:`QT4_ADD_RESOURCES() <FindQt4>` or ``QT5_ADD_RESOURCES()``
-macro. Currently Qt4 and Qt5 are supported.
+commands like :module:`QT4_ADD_RESOURCES() <FindQt4>`, ``QT5_ADD_RESOURCES()``,
+etc. Currently, Qt versions 4 to 6 are supported.
When this property is ``ON``, CMake will handle ``.qrc`` files added
as target sources at build time and invoke ``rcc`` accordingly.
diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst
index cd24f5e59..e0cea97a0 100644
--- a/Help/prop_tgt/AUTOUIC.rst
+++ b/Help/prop_tgt/AUTOUIC.rst
@@ -5,8 +5,8 @@ Should the target be processed with auto-uic (for Qt projects).
:prop_tgt:`AUTOUIC` is a boolean specifying whether CMake will handle
the Qt ``uic`` code generator automatically, i.e. without having to use
-the :module:`QT4_WRAP_UI() <FindQt4>` or ``QT5_WRAP_UI()`` macro. Currently
-Qt4 and Qt5 are supported.
+commands like :module:`QT4_WRAP_UI() <FindQt4>`, ``QT5_WRAP_UI()``, etc.
+Currently, Qt versions 4 to 6 are supported.
This property is initialized by the value of the :variable:`CMAKE_AUTOUIC`
variable if it is set when a target is created.
diff --git a/Help/prop_tgt/CUDA_EXTENSIONS.rst b/Help/prop_tgt/CUDA_EXTENSIONS.rst
index 2ddba0b41..ab467ac40 100644
--- a/Help/prop_tgt/CUDA_EXTENSIONS.rst
+++ b/Help/prop_tgt/CUDA_EXTENSIONS.rst
@@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
This property is initialized by the value of
-the :variable:`CMAKE_CUDA_EXTENSIONS` variable if it is set when a target
-is created.
+the :variable:`CMAKE_CUDA_EXTENSIONS` variable if set when a target is created
+and otherwise by the value of
+:variable:`CMAKE_CUDA_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>`
+(see :policy:`CMP0128`).
diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst
index 5ef57be70..950ba12e6 100644
--- a/Help/prop_tgt/CUDA_STANDARD.rst
+++ b/Help/prop_tgt/CUDA_STANDARD.rst
@@ -12,21 +12,27 @@ flag such as ``-std=gnu++11`` to the compile line.
Supported values are:
``98``
- CUDA C++98
+ CUDA C++98. Note that this maps to the same as ``03`` internally.
+
+``03``
+ CUDA C++03
``11``
CUDA C++11
``14``
- CUDA C++14
+ CUDA C++14. While CMake 3.8 and later *recognize* ``14`` as a valid value,
+ CMake 3.9 was the first version to include support for any compiler.
``17``
- CUDA C++17
+ CUDA C++17. While CMake 3.8 and later *recognize* ``17`` as a valid value,
+ CMake 3.18 was the first version to include support for any compiler.
``20``
.. versionadded:: 3.12
- CUDA C++20
+ CUDA C++20. While CMake 3.12 and later *recognize* ``20`` as a valid value,
+ CMake 3.18 was the first version to include support for any compiler.
``23``
.. versionadded:: 3.20
@@ -43,7 +49,7 @@ means that using:
with a compiler which does not support ``-std=gnu++11`` or an equivalent
flag will not result in an error or warning, but will instead add the
-``-std=gnu++98`` flag if supported. This "decay" behavior may be controlled
+``-std=gnu++03`` flag if supported. This "decay" behavior may be controlled
with the :prop_tgt:`CUDA_STANDARD_REQUIRED` target property.
Additionally, the :prop_tgt:`CUDA_EXTENSIONS` target property may be used to
control whether compiler-specific extensions are enabled on a per-target basis.
diff --git a/Help/prop_tgt/CXX_EXTENSIONS.rst b/Help/prop_tgt/CXX_EXTENSIONS.rst
index bda531ec0..9b52504ef 100644
--- a/Help/prop_tgt/CXX_EXTENSIONS.rst
+++ b/Help/prop_tgt/CXX_EXTENSIONS.rst
@@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
This property is initialized by the value of
-the :variable:`CMAKE_CXX_EXTENSIONS` variable if it is set when a target
-is created.
+the :variable:`CMAKE_CXX_EXTENSIONS` variable if set when a target is created
+and otherwise by the value of
+:variable:`CMAKE_CXX_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see
+:policy:`CMP0128`).
diff --git a/Help/prop_tgt/C_EXTENSIONS.rst b/Help/prop_tgt/C_EXTENSIONS.rst
index b2abb462f..a53090c57 100644
--- a/Help/prop_tgt/C_EXTENSIONS.rst
+++ b/Help/prop_tgt/C_EXTENSIONS.rst
@@ -15,5 +15,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
This property is initialized by the value of
-the :variable:`CMAKE_C_EXTENSIONS` variable if it is set when a target
-is created.
+the :variable:`CMAKE_C_EXTENSIONS` variable if set when a target is created and
+otherwise by the value of
+:variable:`CMAKE_C_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see
+:policy:`CMP0128`).
diff --git a/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst
new file mode 100644
index 000000000..3533ef9c8
--- /dev/null
+++ b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst
@@ -0,0 +1,16 @@
+Fortran_BUILDING_INSTRINSIC_MODULES
+-----------------------------------
+
+.. versionadded:: 3.22
+
+Instructs the CMake Fortran preprocessor that the target is building
+Fortran intrinsics for building a Fortran compiler.
+
+This property is off by default and should be turned only on projects
+that build a Fortran compiler. It should not be turned on for projects
+that use a Fortran compiler.
+
+Turning this property on will correctly add dependencies for building
+Fortran intrinsic modules whereas turning the property off will ignore
+Fortran intrinsic modules in the dependency graph as they are supplied
+by the compiler itself.
diff --git a/Help/prop_tgt/HIP_EXTENSIONS.rst b/Help/prop_tgt/HIP_EXTENSIONS.rst
new file mode 100644
index 000000000..d1475c964
--- /dev/null
+++ b/Help/prop_tgt/HIP_EXTENSIONS.rst
@@ -0,0 +1,21 @@
+HIP_EXTENSIONS
+--------------
+
+.. versionadded:: 3.21
+
+Boolean specifying whether compiler specific extensions are requested.
+
+This property specifies whether compiler specific extensions should be
+used. For some compilers, this results in adding a flag such
+as ``-std=gnu++11`` instead of ``-std=c++11`` to the compile line. This
+property is ``ON`` by default. The basic HIP/C++ standard level is
+controlled by the :prop_tgt:`HIP_STANDARD` target property.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
+
+This property is initialized by the value of
+the :variable:`CMAKE_HIP_EXTENSIONS` variable if set when a target is created
+and otherwise by the value of
+:variable:`CMAKE_HIP_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>` (see
+:policy:`CMP0128`).
diff --git a/Help/prop_tgt/HIP_STANDARD.rst b/Help/prop_tgt/HIP_STANDARD.rst
new file mode 100644
index 000000000..0c767c629
--- /dev/null
+++ b/Help/prop_tgt/HIP_STANDARD.rst
@@ -0,0 +1,48 @@
+HIP_STANDARD
+------------
+
+.. versionadded:: 3.21
+
+The HIP/C++ standard requested to build this target.
+
+Supported values are:
+
+``98``
+ HIP C++98
+
+``11``
+ HIP C++11
+
+``14``
+ HIP C++14
+
+``17``
+ HIP C++17
+
+``20``
+ HIP C++20
+
+``23``
+ HIP C++23
+
+If the value requested does not result in a compile flag being added for
+the compiler in use, a previous standard flag will be added instead. This
+means that using:
+
+.. code-block:: cmake
+
+ set_property(TARGET tgt PROPERTY HIP_STANDARD 11)
+
+with a compiler which does not support ``-std=gnu++11`` or an equivalent
+flag will not result in an error or warning, but will instead add the
+``-std=gnu++98`` flag if supported. This "decay" behavior may be controlled
+with the :prop_tgt:`HIP_STANDARD_REQUIRED` target property.
+Additionally, the :prop_tgt:`HIP_EXTENSIONS` target property may be used to
+control whether compiler-specific extensions are enabled on a per-target basis.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
+
+This property is initialized by the value of
+the :variable:`CMAKE_HIP_STANDARD` variable if it is set when a target
+is created.
diff --git a/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst b/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst
new file mode 100644
index 000000000..e56209a3c
--- /dev/null
+++ b/Help/prop_tgt/HIP_STANDARD_REQUIRED.rst
@@ -0,0 +1,19 @@
+HIP_STANDARD_REQUIRED
+---------------------
+
+.. versionadded:: 3.21
+
+Boolean describing whether the value of :prop_tgt:`HIP_STANDARD` is a requirement.
+
+If this property is set to ``ON``, then the value of the
+:prop_tgt:`HIP_STANDARD` target property is treated as a requirement. If this
+property is ``OFF`` or unset, the :prop_tgt:`HIP_STANDARD` target property is
+treated as optional and may "decay" to a previous standard if the requested is
+not available.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
+
+This property is initialized by the value of
+the :variable:`CMAKE_HIP_STANDARD_REQUIRED` variable if it is set when a
+target is created.
diff --git a/Help/prop_tgt/LANG_EXTENSIONS.rst b/Help/prop_tgt/LANG_EXTENSIONS.rst
new file mode 100644
index 000000000..afc2ad367
--- /dev/null
+++ b/Help/prop_tgt/LANG_EXTENSIONS.rst
@@ -0,0 +1,24 @@
+<LANG>_EXTENSIONS
+-----------------
+
+The variations are:
+
+* :prop_tgt:`C_EXTENSIONS`
+* :prop_tgt:`CXX_EXTENSIONS`
+* :prop_tgt:`CUDA_EXTENSIONS`
+* :prop_tgt:`HIP_EXTENSIONS`
+* :prop_tgt:`OBJC_EXTENSIONS`
+* :prop_tgt:`OBJCXX_EXTENSIONS`
+
+These properties specify whether compiler-specific extensions are requested.
+
+These properties are initialized by the value of the
+:variable:`CMAKE_<LANG>_EXTENSIONS` variable if it is set when a target is
+created and otherwise by the value of
+:variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT` (see :policy:`CMP0128`).
+
+For supported CMake versions see the respective pages.
+To control language standard versions see :prop_tgt:`<LANG>_STANDARD`.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/prop_tgt/LANG_STANDARD.rst b/Help/prop_tgt/LANG_STANDARD.rst
new file mode 100644
index 000000000..bd377eccd
--- /dev/null
+++ b/Help/prop_tgt/LANG_STANDARD.rst
@@ -0,0 +1,26 @@
+<LANG>_STANDARD
+---------------
+
+The variations are:
+
+* :prop_tgt:`C_STANDARD`
+* :prop_tgt:`CXX_STANDARD`
+* :prop_tgt:`CUDA_STANDARD`
+* :prop_tgt:`HIP_STANDARD`
+* :prop_tgt:`OBJC_STANDARD`
+* :prop_tgt:`OBJCXX_STANDARD`
+
+These properties specify language standard versions which are requested. When a
+newer standard is specified than is supported by the compiler, then it will
+fallback to the latest supported standard. This "decay" behavior may be
+controlled with the :prop_tgt:`<LANG>_STANDARD_REQUIRED` target property.
+
+These properties are initialized by the value of the
+:variable:`CMAKE_<LANG>_STANDARD` variable if it is set when a target is
+created.
+
+For supported values and CMake versions see the respective pages.
+To control compiler-specific extensions see :prop_tgt:`<LANG>_EXTENSIONS`.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst b/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst
new file mode 100644
index 000000000..56ecef85f
--- /dev/null
+++ b/Help/prop_tgt/LANG_STANDARD_REQUIRED.rst
@@ -0,0 +1,26 @@
+<LANG>_STANDARD_REQUIRED
+------------------------
+
+The variations are:
+
+* :prop_tgt:`C_STANDARD_REQUIRED`
+* :prop_tgt:`CXX_STANDARD_REQUIRED`
+* :prop_tgt:`CUDA_STANDARD_REQUIRED`
+* :prop_tgt:`HIP_STANDARD_REQUIRED`
+* :prop_tgt:`OBJC_STANDARD_REQUIRED`
+* :prop_tgt:`OBJCXX_STANDARD_REQUIRED`
+
+These properties specify whether the value of :prop_tgt:`<LANG>_STANDARD` is a
+requirement. When ``OFF`` or unset, the :prop_tgt:`<LANG>_STANDARD` target
+property is treated as optional and may "decay" to a previous standard if the
+requested is not available.
+
+These properties are initialized by the value of the
+:variable:`CMAKE_<LANG>_STANDARD_REQUIRED` variable if it is set when a target
+is created.
+
+For supported CMake versions see the respective pages.
+To control language standard versions see :prop_tgt:`<LANG>_STANDARD`.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/prop_tgt/LINK_WHAT_YOU_USE.rst b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
index 2ed93adfd..d6de0d49c 100644
--- a/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
+++ b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
@@ -1,16 +1,22 @@
LINK_WHAT_YOU_USE
----------------------------
+-----------------
.. versionadded:: 3.7
-This is a boolean option that when set to ``TRUE`` will automatically run
-``ldd -r -u`` on the target after it is linked. In addition, the linker flag
-``-Wl,--no-as-needed`` will be passed to the target with the link command so
-that all libraries specified on the command line will be linked into the
-target. This will result in the link producing a list of libraries that
-provide no symbols used by this target but are being linked to it.
-This is only applicable to executable and shared library targets and
-will only work when ld and ldd accept the flags used.
+This is a boolean option that, when set to ``TRUE``, will automatically run
+contents of variable :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK` on the target
+after it is linked. In addition, the linker flag specified by variable
+:variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` will be passed to the target
+with the link command so that all libraries specified on the command line will
+be linked into the target. This will result in the link producing a list of
+libraries that provide no symbols used by this target but are being linked to
+it.
+
+.. note::
+
+ For now, it is only supported for ``ELF`` platforms and is only applicable to
+ executable and shared or module library targets. This property will be
+ ignored for any other targets and configurations.
This property is initialized by the value of
the :variable:`CMAKE_LINK_WHAT_YOU_USE` variable if it is set
diff --git a/Help/prop_tgt/OBJCXX_EXTENSIONS.rst b/Help/prop_tgt/OBJCXX_EXTENSIONS.rst
index 8a254f20a..2a15dec90 100644
--- a/Help/prop_tgt/OBJCXX_EXTENSIONS.rst
+++ b/Help/prop_tgt/OBJCXX_EXTENSIONS.rst
@@ -18,5 +18,7 @@ If the property is not set, and the project has set the :prop_tgt:`CXX_EXTENSION
the value of :prop_tgt:`CXX_EXTENSIONS` is set for :prop_tgt:`OBJCXX_EXTENSIONS`.
This property is initialized by the value of
-the :variable:`CMAKE_OBJCXX_EXTENSIONS` variable if it is set when a target
-is created.
+the :variable:`CMAKE_OBJCXX_EXTENSIONS` variable if set when a target is
+created and otherwise by the value of
+:variable:`CMAKE_OBJCXX_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>`
+(see :policy:`CMP0128`).
diff --git a/Help/prop_tgt/OBJC_EXTENSIONS.rst b/Help/prop_tgt/OBJC_EXTENSIONS.rst
index ef1c7543c..cd72e5fcc 100644
--- a/Help/prop_tgt/OBJC_EXTENSIONS.rst
+++ b/Help/prop_tgt/OBJC_EXTENSIONS.rst
@@ -18,5 +18,7 @@ See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
This property is initialized by the value of
-the :variable:`CMAKE_OBJC_EXTENSIONS` variable if it is set when a target
-is created.
+the :variable:`CMAKE_OBJC_EXTENSIONS` variable if set when a target is created
+and otherwise by the value of
+:variable:`CMAKE_OBJC_EXTENSIONS_DEFAULT <CMAKE_<LANG>_EXTENSIONS_DEFAULT>`
+(see :policy:`CMP0128`).
diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst
index 462d2be81..e1c6172b2 100644
--- a/Help/release/3.21.rst
+++ b/Help/release/3.21.rst
@@ -334,10 +334,3 @@ Changes made since CMake 3.21.0 include the following.
* The :generator:`Visual Studio 17 2022` generator is now based on the
"Visual Studio 2022" release candidates. Previously it was based on
preview versions.
-
-3.21.5, 3.21.6, 3.21.7
-----------------------
-
-These versions made no changes to documented features or interfaces.
-Some implementation updates were made to support ecosystem changes
-and/or fix regressions.
diff --git a/Help/release/3.22.rst b/Help/release/3.22.rst
new file mode 100644
index 000000000..fcb655d19
--- /dev/null
+++ b/Help/release/3.22.rst
@@ -0,0 +1,144 @@
+CMake 3.22 Release Notes
+************************
+
+.. only:: html
+
+ .. contents::
+
+Changes made since CMake 3.21 include the following.
+
+New Features
+============
+
+Commands
+--------
+
+* The :command:`cmake_host_system_information` command can now query
+ `OS identification variables`_ from the :file:`/etc/os-release` file.
+
+* The :command:`string(TIMESTAMP)` command now supports the ``%V``
+ specifier for ISO 8601 week numbers.
+
+.. _`OS identification variables`: https://www.freedesktop.org/software/systemd/man/os-release.html
+
+Variables
+---------
+
+* The :envvar:`CMAKE_BUILD_TYPE` environment variable was added to
+ provide a default value for the :variable:`CMAKE_BUILD_TYPE` variable.
+
+* The :envvar:`CMAKE_CONFIGURATION_TYPES` environment variable was added to
+ provide a default value for the :variable:`CMAKE_CONFIGURATION_TYPES`
+ variable.
+
+* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to
+ tell :command:`install` rules (implemented by :command:`file(INSTALL)`)
+ to install symbolic links instead of copying of files.
+
+* The :variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` and
+ :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK` variables were added to
+ control the linker flag and check used by the
+ :prop_tgt:`LINK_WHAT_YOU_USE` target property.
+
+* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable
+ was added to turn a non-REQUIRED :command:`find_package` call into
+ a REQUIRED one.
+
+Properties
+----------
+
+* The :prop_tgt:`<LANG>_EXTENSIONS` target property is now initialized to
+ :variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`, detected from the compiler.
+ See :policy:`CMP0128`.
+
+* The :prop_sf:`VS_SETTINGS` source file property is now supported for
+ all source file types. Previously it worked only for non-built sources.
+
+Modules
+-------
+
+* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option`
+ macro now supports full :ref:`Condition Syntax`.
+ See policy :policy:`CMP0127`.
+
+* The :module:`FetchContent` module now passes through the
+ :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`,
+ :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables (when
+ defined) to the underlying :module:`ExternalProject` sub-build.
+ Previously, those variables were silently ignored by :module:`FetchContent`.
+
+* The :module:`FindBLAS` and :module:`FindLAPACK` modules gained
+ a ``BLA_SIZEOF_INTEGER`` option to find a BLAS/LAPACK whose ABI
+ uses a specific integer size.
+
+* The :module:`FindJasper` module now provides an imported target.
+
+* The :module:`FindMatlab` module now provides imported targets.
+
+* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN`
+ variable to specify arguments to ``pkg-config`` calls.
+
+* The :module:`GoogleTest` module :command:`gtest_discover_tests`
+ function gained a ``TEST_FILTER`` option to filter tests using
+ ``--gtest_filter`` during test discovery.
+
+* The :module:`UseSWIG` module, for :ref:`Visual Studio Generators`,
+ can now use the ``swig`` tool to generate implicit dependencies.
+
+CTest
+-----
+
+* :manual:`ctest(1)` learned to recognize labels attached to a test at run time.
+ Previously it was only possible to attach labels to tests at configure time
+ by using the :prop_test:`LABELS` test property.
+ See :ref:`Additional Test Measurements` for more information.
+
+* :manual:`ctest(1)` learned to be able to modify the environment for a test
+ through the :prop_test:`ENVIRONMENT_MODIFICATION` property. This is allows
+ for updates to environment variables based on the environment present at
+ test time.
+
+* The :command:`ctest_memcheck` command now also generates a
+ :file:`DynamicAnalysis-Test.xml` file which may be used to submit test
+ results to CDash.
+
+CPack
+-----
+
+* The :cpack_gen:`CPack DEB Generator` gained the
+ option to set :variable:`CPACK_DEBIAN_COMPRESSION_TYPE` to ``zstd``,
+ which enables Zstandard compression for deb packages.
+
+* The :cpack_gen:`CPack NSIS Generator` gained a new
+ :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` variable to suppress
+ the license page in the installer.
+
+* The :cpack_gen:`CPack RPM Generator` gained the
+ :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option to avoid scanning
+ specific paths for dependencies.
+
+Deprecated and Removed Features
+===============================
+
+* The :generator:`Visual Studio 10 2010` generator is now deprecated
+ and will be removed in a future version of CMake.
+
+Other Changes
+=============
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality now
+ correctly disables or enables compiler extensions when no standard level is
+ specified and avoids unnecessarily adding language standard flags if the
+ requested settings match the compiler's defaults. See :policy:`CMP0128`.
+
+* The :manual:`Compile Features <cmake-compile-features(7)>` functionality
+ now ignores features for languages that are not enabled.
+
+* The :ref:`Ninja Generators` now implement the ``edit_cache`` target
+ using :manual:`ccmake(1)` if available.
+
+* The :generator:`Ninja` and :generator:`NMake Makefiles` generators
+ now use the MSVC ``-external:I`` flag for system includes.
+ This became available as of VS 16.10 (toolchain version 14.29.30037).
+
+* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 75667e54f..3d2ed4310 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -13,6 +13,7 @@ Releases
.. toctree::
:maxdepth: 1
+ 3.22 <3.22>
3.21 <3.21>
3.20 <3.20>
3.19 <3.19>
diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst
index 405f7d590..bb95436ad 100644
--- a/Help/variable/CMAKE_BUILD_TYPE.rst
+++ b/Help/variable/CMAKE_BUILD_TYPE.rst
@@ -1,25 +1,21 @@
CMAKE_BUILD_TYPE
----------------
-Specifies the build type on single-configuration generators.
+Specifies the build type on single-configuration generators (e.g.
+:ref:`Makefile Generators` or :generator:`Ninja`). Typical values include
+``Debug``, ``Release``, ``RelWithDebInfo`` and ``MinSizeRel``, but custom
+build types can also be defined.
-This statically specifies what build type (configuration) will be
-built in this build tree. Possible values are empty, ``Debug``, ``Release``,
-``RelWithDebInfo``, ``MinSizeRel``, ... This variable is only meaningful to
-single-configuration generators (such as :ref:`Makefile Generators` and
-:generator:`Ninja`) i.e. those which choose a single configuration when CMake
-runs to generate a build tree as opposed to multi-configuration generators
-which offer selection of the build configuration within the generated build
-environment. There are many per-config properties and variables
-(usually following clean ``SOME_VAR_<CONFIG>`` order conventions), such as
-``CMAKE_C_FLAGS_<CONFIG>``, specified as uppercase:
-``CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL|...]``. For example,
-in a build tree configured to build type ``Debug``, CMake will see to
-having :variable:`CMAKE_C_FLAGS_DEBUG <CMAKE_<LANG>_FLAGS_DEBUG>` settings get
-added to the :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` settings. See
-also :variable:`CMAKE_CONFIGURATION_TYPES`.
+This variable is initialized by the first :command:`project` or
+:command:`enable_language` command called in a project when a new build
+tree is first created. If the :envvar:`CMAKE_BUILD_TYPE` environment
+variable is set, its value is used. Otherwise, a toolchain-specific
+default is chosen when a language is enabled. The default value is often
+an empty string, but this is usually not desirable and one of the other
+standard build types is usually more appropriate.
-Note that configuration names are case-insensitive. The value of this
-variable will be the same as it is specified when invoking CMake.
-For instance, if ``-DCMAKE_BUILD_TYPE=ReLeAsE`` is specified, then the
-value of ``CMAKE_BUILD_TYPE`` will be ``ReLeAsE``.
+Depending on the situation, the value of this variable may be treated
+case-sensitively or case-insensitively. See :ref:`Build Configurations`
+for discussion of this and other related topics.
+
+For multi-config generators, see :variable:`CMAKE_CONFIGURATION_TYPES`.
diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
index 8fcc79869..75ff8a12a 100644
--- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
+++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
@@ -1,12 +1,20 @@
CMAKE_CONFIGURATION_TYPES
-------------------------
-Specifies the available build types on multi-config generators.
+Specifies the available build types (configurations) on multi-config
+generators (e.g. :ref:`Visual Studio <Visual Studio Generators>`,
+:generator:`Xcode`, or :generator:`Ninja Multi-Config`). Typical values
+include ``Debug``, ``Release``, ``RelWithDebInfo`` and ``MinSizeRel``,
+but custom build types can also be defined.
-This specifies what build types (configurations) will be available
-such as ``Debug``, ``Release``, ``RelWithDebInfo`` etc. This has reasonable
-defaults on most platforms, but can be extended to provide other build
-types.
+This variable is initialized by the first :command:`project` or
+:command:`enable_language` command called in a project when a new build
+tree is first created. If the :envvar:`CMAKE_CONFIGURATION_TYPES`
+environment variable is set, its value is used. Otherwise, the default
+value is generator-specific.
-See :variable:`CMAKE_BUILD_TYPE` for specifying the configuration with
-single-config generators.
+Depending on the situation, the values in this variable may be treated
+case-sensitively or case-insensitively. See :ref:`Build Configurations`
+for discussion of this and other related topics.
+
+For single-config generators, see :variable:`CMAKE_BUILD_TYPE`.
diff --git a/Help/variable/CMAKE_CUDA_EXTENSIONS.rst b/Help/variable/CMAKE_CUDA_EXTENSIONS.rst
index b86c0ea39..12749ce59 100644
--- a/Help/variable/CMAKE_CUDA_EXTENSIONS.rst
+++ b/Help/variable/CMAKE_CUDA_EXTENSIONS.rst
@@ -3,11 +3,8 @@ CMAKE_CUDA_EXTENSIONS
.. versionadded:: 3.8
-Default value for :prop_tgt:`CUDA_EXTENSIONS` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CUDA_EXTENSIONS`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CUDA_EXTENSIONS` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_CUDA_STANDARD.rst b/Help/variable/CMAKE_CUDA_STANDARD.rst
index 798ab1e74..ee9395aef 100644
--- a/Help/variable/CMAKE_CUDA_STANDARD.rst
+++ b/Help/variable/CMAKE_CUDA_STANDARD.rst
@@ -3,11 +3,8 @@ CMAKE_CUDA_STANDARD
.. versionadded:: 3.8
-Default value for :prop_tgt:`CUDA_STANDARD` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CUDA_STANDARD`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CUDA_STANDARD` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst
index ae2f52f8b..0c85a04d7 100644
--- a/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst
+++ b/Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst
@@ -3,11 +3,8 @@ CMAKE_CUDA_STANDARD_REQUIRED
.. versionadded:: 3.8
-Default value for :prop_tgt:`CUDA_STANDARD_REQUIRED` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CUDA_STANDARD_REQUIRED`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CUDA_STANDARD_REQUIRED` target property if set
+when a target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_CXX_EXTENSIONS.rst b/Help/variable/CMAKE_CXX_EXTENSIONS.rst
index ea8c4be70..017f503ae 100644
--- a/Help/variable/CMAKE_CXX_EXTENSIONS.rst
+++ b/Help/variable/CMAKE_CXX_EXTENSIONS.rst
@@ -3,11 +3,8 @@ CMAKE_CXX_EXTENSIONS
.. versionadded:: 3.1
-Default value for :prop_tgt:`CXX_EXTENSIONS` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CXX_EXTENSIONS`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CXX_EXTENSIONS` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_CXX_STANDARD.rst b/Help/variable/CMAKE_CXX_STANDARD.rst
index 8ef8c80e3..33eb89e03 100644
--- a/Help/variable/CMAKE_CXX_STANDARD.rst
+++ b/Help/variable/CMAKE_CXX_STANDARD.rst
@@ -3,11 +3,8 @@ CMAKE_CXX_STANDARD
.. versionadded:: 3.1
-Default value for :prop_tgt:`CXX_STANDARD` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CXX_STANDARD`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CXX_STANDARD` target property if set when a target
+is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst
index f7b2ae92e..1c6c0cc96 100644
--- a/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst
+++ b/Help/variable/CMAKE_CXX_STANDARD_REQUIRED.rst
@@ -3,11 +3,8 @@ CMAKE_CXX_STANDARD_REQUIRED
.. versionadded:: 3.1
-Default value for :prop_tgt:`CXX_STANDARD_REQUIRED` property of targets.
-
-This variable is used to initialize the :prop_tgt:`CXX_STANDARD_REQUIRED`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`CXX_STANDARD_REQUIRED` target property if set when
+a target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_C_EXTENSIONS.rst b/Help/variable/CMAKE_C_EXTENSIONS.rst
index fce8fc722..668052111 100644
--- a/Help/variable/CMAKE_C_EXTENSIONS.rst
+++ b/Help/variable/CMAKE_C_EXTENSIONS.rst
@@ -3,11 +3,8 @@ CMAKE_C_EXTENSIONS
.. versionadded:: 3.1
-Default value for :prop_tgt:`C_EXTENSIONS` property of targets.
-
-This variable is used to initialize the :prop_tgt:`C_EXTENSIONS`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`C_EXTENSIONS` target property if set when a target
+is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_C_STANDARD.rst b/Help/variable/CMAKE_C_STANDARD.rst
index 64ef8ce29..ec1e5131e 100644
--- a/Help/variable/CMAKE_C_STANDARD.rst
+++ b/Help/variable/CMAKE_C_STANDARD.rst
@@ -3,11 +3,8 @@ CMAKE_C_STANDARD
.. versionadded:: 3.1
-Default value for :prop_tgt:`C_STANDARD` property of targets.
-
-This variable is used to initialize the :prop_tgt:`C_STANDARD`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`C_STANDARD` target property if set when a target
+is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst
index e70b6bd26..2bd9d51b5 100644
--- a/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst
+++ b/Help/variable/CMAKE_C_STANDARD_REQUIRED.rst
@@ -3,11 +3,8 @@ CMAKE_C_STANDARD_REQUIRED
.. versionadded:: 3.1
-Default value for :prop_tgt:`C_STANDARD_REQUIRED` property of targets.
-
-This variable is used to initialize the :prop_tgt:`C_STANDARD_REQUIRED`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`C_STANDARD_REQUIRED` target property if set when
+a target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
index ed600202c..f77e93916 100644
--- a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
+++ b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
@@ -14,3 +14,5 @@ the package has already been found in a previous CMake run, the
variables which have been stored in the cache will still be there. In
that case it is recommended to remove the cache variables for this
package from the cache using the cache editor or :manual:`cmake(1)` ``-U``
+
+See also the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable.
diff --git a/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst b/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst
index 4a64e33e9..c2c2609df 100644
--- a/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst
+++ b/Help/variable/CMAKE_FIND_LIBRARY_SUFFIXES.rst
@@ -5,5 +5,8 @@ Suffixes to append when looking for libraries.
This specifies what suffixes to add to library names when the
:command:`find_library` command looks for libraries. On Windows systems this
-is typically ``.lib`` and ``.dll``, meaning that when trying to find the
-``foo`` library it will look for ``foo.dll`` etc.
+is typically ``.lib`` and, depending on the compiler, ``.dll.a``, ``.a``
+(e.g. GCC and Clang), so when it tries to find the ``foo`` library, it will
+look for ``[<prefix>]foo.lib`` and/or ``[<prefix>]foo[.dll].a``, depending on
+the compiler used and the ``<prefix>`` specified in the
+:variable:`CMAKE_FIND_LIBRARY_PREFIXES`.
diff --git a/Help/variable/CMAKE_HIP_EXTENSIONS.rst b/Help/variable/CMAKE_HIP_EXTENSIONS.rst
new file mode 100644
index 000000000..13987dcda
--- /dev/null
+++ b/Help/variable/CMAKE_HIP_EXTENSIONS.rst
@@ -0,0 +1,10 @@
+CMAKE_HIP_EXTENSIONS
+--------------------
+
+.. versionadded:: 3.21
+
+Default value for :prop_tgt:`HIP_EXTENSIONS` target property if set when a
+target is created.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_HIP_STANDARD.rst b/Help/variable/CMAKE_HIP_STANDARD.rst
new file mode 100644
index 000000000..5f1514586
--- /dev/null
+++ b/Help/variable/CMAKE_HIP_STANDARD.rst
@@ -0,0 +1,10 @@
+CMAKE_HIP_STANDARD
+------------------
+
+.. versionadded:: 3.21
+
+Default value for :prop_tgt:`HIP_STANDARD` target property if set when a target
+is created.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst
new file mode 100644
index 000000000..5d35e4e28
--- /dev/null
+++ b/Help/variable/CMAKE_HIP_STANDARD_REQUIRED.rst
@@ -0,0 +1,10 @@
+CMAKE_HIP_STANDARD_REQUIRED
+---------------------------
+
+.. versionadded:: 3.21
+
+Default value for :prop_tgt:`HIP_STANDARD_REQUIRED` target property if set when
+a target is created.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst b/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst
new file mode 100644
index 000000000..128b1fbbe
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_COMPILER_FRONTEND_VARIANT.rst
@@ -0,0 +1,18 @@
+CMAKE_<LANG>_COMPILER_FRONTEND_VARIANT
+--------------------------------------
+
+.. versionadded:: 3.14
+
+Identification string of the compiler frontend variant.
+
+Some compilers have multiple, different frontends for accepting command
+line options. (For example ``Clang`` originally only had a frontend
+compatible with the ``GNU`` compiler but since its port to Windows
+(``Clang-Cl``) it now also supports a frontend compatible with ``MSVC``.)
+When CMake detects such a compiler it sets this
+variable to what would have been the :variable:`CMAKE_<LANG>_COMPILER_ID` for
+the compiler whose frontend it resembles.
+
+.. note::
+ In other words, this variable describes what command line options
+ and language extensions the compiler frontend expects.
diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS.rst b/Help/variable/CMAKE_LANG_EXTENSIONS.rst
new file mode 100644
index 000000000..3a32002f6
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_EXTENSIONS.rst
@@ -0,0 +1,20 @@
+CMAKE_<LANG>_EXTENSIONS
+-----------------------
+
+The variations are:
+
+* :variable:`CMAKE_C_EXTENSIONS`
+* :variable:`CMAKE_CXX_EXTENSIONS`
+* :variable:`CMAKE_CUDA_EXTENSIONS`
+* :variable:`CMAKE_HIP_EXTENSIONS`
+* :variable:`CMAKE_OBJC_EXTENSIONS`
+* :variable:`CMAKE_OBJCXX_EXTENSIONS`
+
+Default values for :prop_tgt:`<LANG>_EXTENSIONS` target properties if set when
+a target is created. For the compiler's default setting see
+:variable:`CMAKE_<LANG>_EXTENSIONS_DEFAULT`.
+
+For supported CMake versions see the respective pages.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst
new file mode 100644
index 000000000..a66453acb
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_EXTENSIONS_DEFAULT.rst
@@ -0,0 +1,10 @@
+CMAKE_<LANG>_EXTENSIONS_DEFAULT
+-------------------------------
+
+.. versionadded:: 3.22
+
+Compiler's default extensions mode. Used as the default for the
+:prop_tgt:`<LANG>_EXTENSIONS` target property when
+:variable:`CMAKE_<LANG>_EXTENSIONS` is not set (see :policy:`CMP0128`).
+
+This variable is read-only. Modifying it is undefined behavior.
diff --git a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
index e9e04be6e..081c4da6b 100644
--- a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
+++ b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
@@ -6,8 +6,20 @@ Implicit linker search path detected for language ``<LANG>``.
Compilers typically pass directories containing language runtime
libraries and default library search paths when they invoke a linker.
These paths are implicit linker search directories for the compiler's
-language. CMake automatically detects these directories for each
-language and reports the results in this variable.
+language. For each language enabled by the :command:`project` or
+:command:`enable_language` command, CMake automatically detects these
+directories and reports the results in this variable.
+
+When linking to a static library, CMake adds the implicit link directories
+from this variable for each language used in the static library (except
+the language whose compiler is used to drive linking). In the case of an
+imported static library, the :prop_tgt:`IMPORTED_LINK_INTERFACE_LANGUAGES`
+target property lists the languages whose implicit link information is
+needed. If any of the languages is not enabled, its value for the
+``CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES`` variable may instead be provided
+by the project. Or, a :variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>`
+may set the variable to a value known for the specified toolchain. It will
+either be overridden when the language is enabled, or used as a fallback.
Some toolchains read implicit directories from an environment variable such as
``LIBRARY_PATH``. If using such an environment variable, keep its value
@@ -18,3 +30,5 @@ If policy :policy:`CMP0060` is not set to ``NEW``, then when a library in one
of these directories is given by full path to :command:`target_link_libraries`
CMake will generate the ``-l<name>`` form on link lines for historical
purposes.
+
+See also the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES` variable.
diff --git a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst
index ec164774b..0c25489ca 100644
--- a/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst
+++ b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst
@@ -5,6 +5,20 @@ Implicit link libraries and flags detected for language ``<LANG>``.
Compilers typically pass language runtime library names and other
flags when they invoke a linker. These flags are implicit link
-options for the compiler's language. CMake automatically detects
-these libraries and flags for each language and reports the results in
-this variable.
+options for the compiler's language. For each language enabled
+by the :command:`project` or :command:`enable_language` command,
+CMake automatically detects these libraries and flags and reports
+the results in this variable.
+
+When linking to a static library, CMake adds the implicit link libraries and
+flags from this variable for each language used in the static library (except
+the language whose compiler is used to drive linking). In the case of an
+imported static library, the :prop_tgt:`IMPORTED_LINK_INTERFACE_LANGUAGES`
+target property lists the languages whose implicit link information is
+needed. If any of the languages is not enabled, its value for the
+``CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES`` variable may instead be provided
+by the project. Or, a :variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>`
+may set the variable to a value known for the specified toolchain. It will
+either be overridden when the language is enabled, or used as a fallback.
+
+See also the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES` variable.
diff --git a/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst b/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst
new file mode 100644
index 000000000..500453039
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG.rst
@@ -0,0 +1,9 @@
+CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG
+-----------------------------------
+
+.. versionadded:: 3.22
+
+Linker flag to be used to configure linker so that all specified libraries on
+the command line will be linked into the target.
+
+See also variable :variable:`CMAKE_LINK_WHAT_YOU_USE_CHECK`.
diff --git a/Help/variable/CMAKE_LANG_SIMULATE_ID.rst b/Help/variable/CMAKE_LANG_SIMULATE_ID.rst
index 15c87a186..3226352a2 100644
--- a/Help/variable/CMAKE_LANG_SIMULATE_ID.rst
+++ b/Help/variable/CMAKE_LANG_SIMULATE_ID.rst
@@ -1,9 +1,13 @@
CMAKE_<LANG>_SIMULATE_ID
------------------------
-Identification string of "simulated" compiler.
+Identification string of the "simulated" compiler.
Some compilers simulate other compilers to serve as drop-in
replacements. When CMake detects such a compiler it sets this
variable to what would have been the :variable:`CMAKE_<LANG>_COMPILER_ID` for
the simulated compiler.
+
+.. note::
+ In other words, this variable describes the ABI compatibility
+ of the generated code.
diff --git a/Help/variable/CMAKE_LANG_STANDARD.rst b/Help/variable/CMAKE_LANG_STANDARD.rst
new file mode 100644
index 000000000..0c41e1968
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_STANDARD.rst
@@ -0,0 +1,19 @@
+CMAKE_<LANG>_STANDARD
+---------------------
+
+The variations are:
+
+* :variable:`CMAKE_C_STANDARD`
+* :variable:`CMAKE_CXX_STANDARD`
+* :variable:`CMAKE_CUDA_STANDARD`
+* :variable:`CMAKE_HIP_STANDARD`
+* :variable:`CMAKE_OBJC_STANDARD`
+* :variable:`CMAKE_OBJCXX_STANDARD`
+
+Default values for :prop_tgt:`<LANG>_STANDARD` target properties if set when a
+target is created.
+
+For supported CMake versions see the respective pages.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst b/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst
new file mode 100644
index 000000000..eb63d208a
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_STANDARD_DEFAULT.rst
@@ -0,0 +1,7 @@
+CMAKE_<LANG>_STANDARD_DEFAULT
+-----------------------------
+
+.. versionadded:: 3.9
+
+The compiler's default standard for the language ``<LANG>``. Empty if the
+compiler has no conception of standard levels.
diff --git a/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst
new file mode 100644
index 000000000..d7fa9b69b
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_STANDARD_REQUIRED.rst
@@ -0,0 +1,19 @@
+CMAKE_<LANG>_STANDARD_REQUIRED
+------------------------------
+
+The variations are:
+
+* :variable:`CMAKE_C_STANDARD_REQUIRED`
+* :variable:`CMAKE_CXX_STANDARD_REQUIRED`
+* :variable:`CMAKE_CUDA_STANDARD_REQUIRED`
+* :variable:`CMAKE_HIP_STANDARD_REQUIRED`
+* :variable:`CMAKE_OBJC_STANDARD_REQUIRED`
+* :variable:`CMAKE_OBJCXX_STANDARD_REQUIRED`
+
+Default values for :prop_tgt:`<LANG>_STANDARD_REQUIRED` target properties if
+set when a target is created.
+
+For supported CMake versions see the respective pages.
+
+See the :manual:`cmake-compile-features(7)` manual for information on
+compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
index 06b3aa89b..bca4519a8 100644
--- a/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
+++ b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
@@ -1,5 +1,5 @@
CMAKE_LINK_WHAT_YOU_USE
----------------------------------
+-----------------------
.. versionadded:: 3.7
diff --git a/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst
new file mode 100644
index 000000000..e626641bc
--- /dev/null
+++ b/Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst
@@ -0,0 +1,10 @@
+CMAKE_LINK_WHAT_YOU_USE_CHECK
+-----------------------------
+
+.. versionadded:: 3.22
+
+Defines the command executed after the link step to check libraries usage.
+This check is currently only defined on ``ELF`` platforms with value
+``ldd -u -r``.
+
+See also :variable:`CMAKE_<LANG>_LINK_WHAT_YOU_USE_FLAG` variables.
diff --git a/Help/variable/CMAKE_NETRC.rst b/Help/variable/CMAKE_NETRC.rst
index 2c64a8149..bddfca555 100644
--- a/Help/variable/CMAKE_NETRC.rst
+++ b/Help/variable/CMAKE_NETRC.rst
@@ -3,9 +3,11 @@ CMAKE_NETRC
.. versionadded:: 3.11
-This variable is used to initialize the ``NETRC`` option for
-:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the
-module :module:`ExternalProject`. See those commands for additional
-information.
+This variable is used to initialize the ``NETRC`` option for the
+:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands.
+See those commands for additional information.
+
+This variable is also used by the :module:`ExternalProject` and
+:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`.
The local option takes precedence over this variable.
diff --git a/Help/variable/CMAKE_NETRC_FILE.rst b/Help/variable/CMAKE_NETRC_FILE.rst
index 97a645efe..af98170b9 100644
--- a/Help/variable/CMAKE_NETRC_FILE.rst
+++ b/Help/variable/CMAKE_NETRC_FILE.rst
@@ -3,9 +3,11 @@ CMAKE_NETRC_FILE
.. versionadded:: 3.11
-This variable is used to initialize the ``NETRC_FILE`` option for
-:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and the
-module :module:`ExternalProject`. See those commands for additional
-information.
+This variable is used to initialize the ``NETRC_FILE`` option for the
+:command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands.
+See those commands for additional information.
+
+This variable is also used by the :module:`ExternalProject` and
+:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`.
The local option takes precedence over this variable.
diff --git a/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst b/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst
index b5225ea68..46736aa7d 100644
--- a/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst
+++ b/Help/variable/CMAKE_OBJCXX_EXTENSIONS.rst
@@ -3,11 +3,8 @@ CMAKE_OBJCXX_EXTENSIONS
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJCXX_EXTENSIONS` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJCXX_EXTENSIONS`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJCXX_EXTENSIONS` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_OBJCXX_STANDARD.rst b/Help/variable/CMAKE_OBJCXX_STANDARD.rst
index 98e462414..0913382a4 100644
--- a/Help/variable/CMAKE_OBJCXX_STANDARD.rst
+++ b/Help/variable/CMAKE_OBJCXX_STANDARD.rst
@@ -3,11 +3,8 @@ CMAKE_OBJCXX_STANDARD
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJCXX_STANDARD` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJCXX_STANDARD`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJCXX_STANDARD` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst
index 4b5e77cf0..9afc4eab4 100644
--- a/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst
+++ b/Help/variable/CMAKE_OBJCXX_STANDARD_REQUIRED.rst
@@ -3,11 +3,8 @@ CMAKE_OBJCXX_STANDARD_REQUIRED
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJCXX_STANDARD_REQUIRED` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJCXX_STANDARD_REQUIRED`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJCXX_STANDARD_REQUIRED` target property if set
+when a target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_OBJC_EXTENSIONS.rst b/Help/variable/CMAKE_OBJC_EXTENSIONS.rst
index d6e3c7dc0..9df11f1c8 100644
--- a/Help/variable/CMAKE_OBJC_EXTENSIONS.rst
+++ b/Help/variable/CMAKE_OBJC_EXTENSIONS.rst
@@ -3,11 +3,8 @@ CMAKE_OBJC_EXTENSIONS
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJC_EXTENSIONS` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJC_EXTENSIONS`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJC_EXTENSIONS` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_OBJC_STANDARD.rst b/Help/variable/CMAKE_OBJC_STANDARD.rst
index fde367dfd..0b9b63ff2 100644
--- a/Help/variable/CMAKE_OBJC_STANDARD.rst
+++ b/Help/variable/CMAKE_OBJC_STANDARD.rst
@@ -3,11 +3,8 @@ CMAKE_OBJC_STANDARD
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJC_STANDARD` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJC_STANDARD`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJC_STANDARD` target property if set when a
+target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst b/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst
index 8d26d952a..c74db55c1 100644
--- a/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst
+++ b/Help/variable/CMAKE_OBJC_STANDARD_REQUIRED.rst
@@ -3,11 +3,8 @@ CMAKE_OBJC_STANDARD_REQUIRED
.. versionadded:: 3.16
-Default value for :prop_tgt:`OBJC_STANDARD_REQUIRED` property of targets.
-
-This variable is used to initialize the :prop_tgt:`OBJC_STANDARD_REQUIRED`
-property on all targets. See that target property for additional
-information.
+Default value for :prop_tgt:`OBJC_STANDARD_REQUIRED` target property if set
+when a target is created.
See the :manual:`cmake-compile-features(7)` manual for information on
compile features and a list of supported compilers.
diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index b991db2df..02316682e 100644
--- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
+++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
@@ -2,8 +2,9 @@ CMAKE_POLICY_WARNING_CMP<NNNN>
------------------------------
Explicitly enable or disable the warning when CMake Policy ``CMP<NNNN>``
-is not set. This is meaningful only for the few policies that do not
-warn by default:
+has not been set explicitly by :command:`cmake_policy` or implicitly
+by :command:`cmake_minimum_required`. This is meaningful
+only for the policies that do not warn by default:
* ``CMAKE_POLICY_WARNING_CMP0025`` controls the warning for
policy :policy:`CMP0025`.
@@ -31,6 +32,8 @@ warn by default:
policy :policy:`CMP0116`.
* ``CMAKE_POLICY_WARNING_CMP0126`` controls the warning for
policy :policy:`CMP0126`.
+* ``CMAKE_POLICY_WARNING_CMP0128`` controls the warning for
+ policy :policy:`CMP0128`.
This variable should not be set by a project in CMake code. Project
developers running CMake may set this variable in their cache to
diff --git a/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst
new file mode 100644
index 000000000..893f1aec8
--- /dev/null
+++ b/Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst
@@ -0,0 +1,14 @@
+CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>
+----------------------------------------
+
+.. versionadded:: 3.22
+
+Variable for making :command:`find_package` call ``REQUIRED``.
+
+Every non-``REQUIRED`` :command:`find_package` call in a project can be
+turned into ``REQUIRED`` by setting the variable
+``CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>`` to ``TRUE``.
+This can be used to assert assumptions about build environment and to
+ensure the build will fail early if they do not hold.
+
+See also the :variable:`CMAKE_DISABLE_FIND_PACKAGE_<PackageName>` variable.
diff --git a/Help/variable/CMAKE_TLS_CAINFO.rst b/Help/variable/CMAKE_TLS_CAINFO.rst
new file mode 100644
index 000000000..07f63660d
--- /dev/null
+++ b/Help/variable/CMAKE_TLS_CAINFO.rst
@@ -0,0 +1,9 @@
+CMAKE_TLS_CAINFO
+----------------
+
+Specify the default value for the :command:`file(DOWNLOAD)` and
+:command:`file(UPLOAD)` commands' ``TLS_CAINFO`` options.
+It is unset by default.
+
+This variable is also used by the :module:`ExternalProject` and
+:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`.
diff --git a/Help/variable/CMAKE_TLS_VERIFY.rst b/Help/variable/CMAKE_TLS_VERIFY.rst
index 24f8a256a..b22f1cefc 100644
--- a/Help/variable/CMAKE_TLS_VERIFY.rst
+++ b/Help/variable/CMAKE_TLS_VERIFY.rst
@@ -5,8 +5,8 @@ Specify the default value for the :command:`file(DOWNLOAD)` and
:command:`file(UPLOAD)` commands' ``TLS_VERIFY`` options.
If not set, the default is *off*.
-This setting is also used by the :module:`ExternalProject` module
-for internal calls to :command:`file(DOWNLOAD)`.
+This variable is also used by the :module:`ExternalProject` and
+:module:`FetchContent` modules for internal calls to :command:`file(DOWNLOAD)`.
TLS verification can help provide confidence that one is connecting
to the desired server. When downloading known content, one should
diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst
new file mode 100644
index 000000000..5ad589719
--- /dev/null
+++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER.rst
@@ -0,0 +1,13 @@
+CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
+------------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework identifier.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkIdentifier`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`.
diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst
new file mode 100644
index 000000000..8dcb3a72b
--- /dev/null
+++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION.rst
@@ -0,0 +1,13 @@
+CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
+-----------------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework targets version.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkTargetsVersion`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_VERSION` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER`.
diff --git a/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst
new file mode 100644
index 000000000..5489f7919
--- /dev/null
+++ b/Help/variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION.rst
@@ -0,0 +1,17 @@
+CMAKE_VS_TARGET_FRAMEWORK_VERSION
+---------------------------------
+
+.. versionadded:: 3.22
+
+Visual Studio target framework version.
+
+In some cases, the :ref:`Visual Studio Generators` may use an explicit value
+for the MSBuild ``TargetFrameworkVersion`` setting in ``.csproj`` files.
+CMake provides the chosen value in this variable.
+
+See the :variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION` variable
+and :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target property to
+specify custom ``TargetFrameworkVersion`` values for project targets.
+
+See also :variable:`CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER` and
+:variable:`CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION`.
diff --git a/Help/variable/MSVC_TOOLSET_VERSION.rst b/Help/variable/MSVC_TOOLSET_VERSION.rst
index 59479af69..c642a9f1d 100644
--- a/Help/variable/MSVC_TOOLSET_VERSION.rst
+++ b/Help/variable/MSVC_TOOLSET_VERSION.rst
@@ -17,7 +17,6 @@ Known toolset version numbers are::
140 = VS 2015 (14.0)
141 = VS 2017 (15.0)
142 = VS 2019 (16.0)
- 143 = VS 2022 (17.0)
Compiler versions newer than those known to CMake will be reported
as the latest known toolset version.
diff --git a/Modules/CMakeASM_MASMInformation.cmake b/Modules/CMakeASM_MASMInformation.cmake
index 6d1e174e3..656b75e7d 100644
--- a/Modules/CMakeASM_MASMInformation.cmake
+++ b/Modules/CMakeASM_MASMInformation.cmake
@@ -8,7 +8,7 @@ set(ASM_DIALECT "_MASM")
set(CMAKE_ASM${ASM_DIALECT}_SOURCE_FILE_EXTENSIONS asm)
-set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> /c /Fo <OBJECT> <SOURCE>")
+set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OBJECT "<CMAKE_ASM${ASM_DIALECT}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -c -Fo <OBJECT> <SOURCE>")
# The ASM_MASM compiler id for this compiler is "MSVC", so fill out the runtime library table.
set(CMAKE_ASM${ASM_DIALECT}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded "")
diff --git a/Modules/CMakeASM_NASMInformation.cmake b/Modules/CMakeASM_NASMInformation.cmake
index dad2750e8..a72575b4a 100644
--- a/Modules/CMakeASM_NASMInformation.cmake
+++ b/Modules/CMakeASM_NASMInformation.cmake
@@ -35,7 +35,7 @@ if(NOT CMAKE_ASM_NASM_OBJECT_FORMAT)
endif()
if(NOT CMAKE_ASM_NASM_COMPILE_OBJECT)
- set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
+ set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
endif()
if(CMAKE_ASM_NASM_COMPILER_ID STREQUAL "NASM")
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index 754f235ba..2b24ff2aa 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -5,6 +5,7 @@ set(CMAKE_C_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@")
set(CMAKE_C_COMPILER_VERSION_INTERNAL "@CMAKE_C_COMPILER_VERSION_INTERNAL@")
set(CMAKE_C_COMPILER_WRAPPER "@CMAKE_C_COMPILER_WRAPPER@")
set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "@CMAKE_C_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@")
set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@")
set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@")
@@ -30,18 +31,9 @@ set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@)
set(CMAKE_C_COMPILER_LOADED 1)
set(CMAKE_C_COMPILER_WORKS @CMAKE_C_COMPILER_WORKS@)
set(CMAKE_C_ABI_COMPILED @CMAKE_C_ABI_COMPILED@)
-set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@)
-set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@)
-if(CMAKE_COMPILER_IS_CYGWIN)
- set(CYGWIN 1)
- set(UNIX 1)
-endif()
set(CMAKE_C_COMPILER_ENV_VAR "CC")
-if(CMAKE_COMPILER_IS_MINGW)
- set(MINGW 1)
-endif()
set(CMAKE_C_COMPILER_ID_RUN 1)
set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
diff --git a/Modules/CMakeCCompilerId.c.in b/Modules/CMakeCCompilerId.c.in
index 1f19c00e2..43ede3e8a 100644
--- a/Modules/CMakeCCompilerId.c.in
+++ b/Modules/CMakeCCompilerId.c.in
@@ -41,23 +41,34 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
#if !defined(__STDC__) && !defined(__clang__)
# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__)
-# define C_DIALECT "90"
+# define C_VERSION "90"
# else
-# define C_DIALECT
+# define C_VERSION
# endif
#elif __STDC_VERSION__ > 201710L
-# define C_DIALECT "23"
+# define C_VERSION "23"
#elif __STDC_VERSION__ >= 201710L
-# define C_DIALECT "17"
+# define C_VERSION "17"
#elif __STDC_VERSION__ >= 201000L
-# define C_DIALECT "11"
+# define C_VERSION "11"
#elif __STDC_VERSION__ >= 199901L
-# define C_DIALECT "99"
+# define C_VERSION "99"
#else
-# define C_DIALECT "90"
+# define C_VERSION "90"
#endif
-const char* info_language_dialect_default =
- "INFO" ":" "dialect_default[" C_DIALECT "]";
+const char* info_language_standard_default =
+ "INFO" ":" "standard_default[" C_VERSION "]";
+
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode.
+#if (defined(__clang__) || defined(__GNUC__) || \
+ defined(__TI_COMPILER_VERSION__)) && \
+ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
/*--------------------------------------------------------------------------*/
@@ -89,7 +100,8 @@ int main(int argc, char* argv[])
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
require += info_cray[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index 6be186575..665f30927 100644
--- a/Modules/CMakeCInformation.cmake
+++ b/Modules/CMakeCInformation.cmake
@@ -91,6 +91,14 @@ if(CMAKE_USER_MAKE_RULES_OVERRIDE_C)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C "${_override}")
endif()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_C_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_C_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
@@ -196,5 +204,3 @@ if(NOT CMAKE_EXECUTABLE_RPATH_LINK_C_FLAG)
endif()
set(CMAKE_C_INFORMATION_LOADED 1)
-
-
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index 56ae7324b..2f3e9a8ce 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -6,6 +6,7 @@ set(CMAKE_CUDA_COMPILER_VERSION "@CMAKE_CUDA_COMPILER_VERSION@")
set(CMAKE_CUDA_DEVICE_LINKER "@CMAKE_CUDA_DEVICE_LINKER@")
set(CMAKE_CUDA_FATBINARY "@CMAKE_CUDA_FATBINARY@")
set(CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT "@CMAKE_CUDA_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_CUDA_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_CUDA_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_CUDA_COMPILE_FEATURES "@CMAKE_CUDA_COMPILE_FEATURES@")
set(CMAKE_CUDA03_COMPILE_FEATURES "@CMAKE_CUDA03_COMPILE_FEATURES@")
set(CMAKE_CUDA11_COMPILE_FEATURES "@CMAKE_CUDA11_COMPILE_FEATURES@")
diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in
index 91039e5ae..bc685a7eb 100644
--- a/Modules/CMakeCUDACompilerId.cu.in
+++ b/Modules/CMakeCUDACompilerId.cu.in
@@ -16,7 +16,7 @@ char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
@CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT@
@CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@
-const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+const char* info_language_standard_default = "INFO" ":" "standard_default["
#if __cplusplus > 202002L
"23"
#elif __cplusplus > 201703L
@@ -32,6 +32,16 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default["
#endif
"]";
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode.
+#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__) && \
+ !defined(_MSC_VER)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
@@ -48,7 +58,8 @@ int main(int argc, char* argv[])
#ifdef SIMULATE_VERSION_MAJOR
require += info_simulate_version[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index a2946f458..e9cfed607 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -100,6 +100,15 @@ if(NOT CMAKE_MODULE_EXISTS)
set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS})
endif()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_CUDA_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_CUDA_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
# add the flags to the cache based
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index d0ce77a7e..534e96055 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -5,6 +5,7 @@ set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "@CMAKE_CXX_COMPILER_VERSION_INTERNAL@")
set(CMAKE_CXX_COMPILER_WRAPPER "@CMAKE_CXX_COMPILER_WRAPPER@")
set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_CXX_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@")
set(CMAKE_CXX98_COMPILE_FEATURES "@CMAKE_CXX98_COMPILE_FEATURES@")
set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
@@ -31,18 +32,9 @@ set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@)
set(CMAKE_CXX_COMPILER_LOADED 1)
set(CMAKE_CXX_COMPILER_WORKS @CMAKE_CXX_COMPILER_WORKS@)
set(CMAKE_CXX_ABI_COMPILED @CMAKE_CXX_ABI_COMPILED@)
-set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@)
-set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@)
-if(CMAKE_COMPILER_IS_CYGWIN)
- set(CYGWIN 1)
- set(UNIX 1)
-endif()
set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
-if(CMAKE_COMPILER_IS_MINGW)
- set(MINGW 1)
-endif()
set(CMAKE_CXX_COMPILER_ID_RUN 1)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in
index 7362a0837..cdf9c1828 100644
--- a/Modules/CMakeCXXCompilerId.cpp.in
+++ b/Modules/CMakeCXXCompilerId.cpp.in
@@ -49,7 +49,7 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
# define CXX_STD __cplusplus
#endif
-const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+const char* info_language_standard_default = "INFO" ":" "standard_default["
#if CXX_STD > 202002L
"23"
#elif CXX_STD > 201703L
@@ -65,6 +65,17 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default["
#endif
"]";
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode.
+#if (defined(__clang__) || defined(__GNUC__) || \
+ defined(__TI_COMPILER_VERSION__)) && \
+ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
@@ -87,7 +98,8 @@ int main(int argc, char* argv[])
#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
require += info_cray[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake
index 944d23609..53abf378d 100644
--- a/Modules/CMakeCXXInformation.cmake
+++ b/Modules/CMakeCXXInformation.cmake
@@ -193,6 +193,15 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
endif()
endforeach()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
# add the flags to the cache based
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
diff --git a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
index 05174de83..bda1d7111 100644
--- a/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
+++ b/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake
@@ -32,5 +32,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
FAIL_REGEX "Warning: illegal option" # SunStudio 12
FAIL_REGEX "[Ww]arning: Invalid suboption" # Fujitsu
FAIL_REGEX "An invalid option .* appears on the command line" # Cray
+ FAIL_REGEX "WARNING: invalid compiler option" # TI armcl
)
endmacro ()
diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake
index 96855d28f..b7c478f64 100644
--- a/Modules/CMakeDependentOption.cmake
+++ b/Modules/CMakeDependentOption.cmake
@@ -10,44 +10,62 @@ Macro to provide an option dependent on other options.
This macro presents an option to the user only if a set of other
conditions are true.
-Usage:
+.. command:: cmake_dependent_option
-.. code-block:: cmake
+ .. code-block:: cmake
- cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>)
+ cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>)
-Where ``<option>`` is available to the user if ``<depends>`` is true. When
-``<option>`` is available, the given ``<help_text>`` and initial ``<value>``
-are used. If the ``<depends>`` condition is not true, ``<option>`` will not be
-presented and will always have the value given by ``<force>``. Any value set by
-the user is preserved for when the option is presented again. Each element in
-the fourth parameter is evaluated as an if-condition, so
-:ref:`Condition Syntax` can be used.
+ Makes ``<option>`` available to the user if ``<depends>`` is true. When
+ ``<option>`` is available, the given ``<help_text>`` and initial ``<value>``
+ are used. If the ``<depends>`` condition is not true, ``<option>`` will not be
+ presented and will always have the value given by ``<force>``. Any value set by
+ the user is preserved for when the option is presented again. In case ``<depends>``
+ is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must
+ be true in order to initialize ``<option>`` with ``<value>``.
Example invocation:
.. code-block:: cmake
- cmake_dependent_option(USE_FOO "Use Foo" ON
- "USE_BAR;NOT USE_ZOT" OFF)
+ cmake_dependent_option(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF)
If ``USE_BAR`` is true and ``USE_ZOT`` is false, this provides an option called
``USE_FOO`` that defaults to ON. Otherwise, it sets ``USE_FOO`` to OFF and
hides the option from the user. If the status of ``USE_BAR`` or ``USE_ZOT``
ever changes, any value for the ``USE_FOO`` option is saved so that when the
option is re-enabled it retains its old value.
+
+.. versionadded:: 3.22
+
+ Full :ref:`Condition Syntax` is now supported. See policy :policy:`CMP0127`.
+
#]=======================================================================]
macro(CMAKE_DEPENDENT_OPTION option doc default depends force)
+ cmake_policy(GET CMP0127 _CDO_CMP0127
+ PARENT_SCOPE # undocumented, do not use outside of CMake
+ )
if(${option}_ISSET MATCHES "^${option}_ISSET$")
set(${option}_AVAILABLE 1)
- foreach(d ${depends})
- string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
- if(${CMAKE_DEPENDENT_OPTION_DEP})
- else()
- set(${option}_AVAILABLE 0)
- endif()
- endforeach()
+ if("x${_CDO_CMP0127}x" STREQUAL "xNEWx")
+ foreach(d ${depends})
+ cmake_language(EVAL CODE "
+ if (${d})
+ else()
+ set(${option}_AVAILABLE 0)
+ endif()"
+ )
+ endforeach()
+ else()
+ foreach(d ${depends})
+ string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
+ if(${CMAKE_DEPENDENT_OPTION_DEP})
+ else()
+ set(${option}_AVAILABLE 0)
+ endif()
+ endforeach()
+ endif()
if(${option}_AVAILABLE)
option(${option} "${doc}" "${default}")
set(${option} "${${option}}" CACHE BOOL "${doc}" FORCE)
@@ -61,4 +79,9 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force)
else()
set(${option} "${${option}_ISSET}")
endif()
+ if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_; ]")
+ cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING)
+ message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}")
+ endif()
+ unset(_CDO_CMP0127)
endmacro()
diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake
index e8b9db797..a1814b7dd 100644
--- a/Modules/CMakeDetermineASMCompiler.cmake
+++ b/Modules/CMakeDetermineASMCompiler.cmake
@@ -125,6 +125,7 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
include(CMakeDetermineCompilerId)
set(userflags)
CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}")
+ set(_variant "")
if("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xIAR")
# primary necessary to detect architecture, so the right archiver and linker can be picked
# eg. "IAR Assembler V8.10.1.12857/W32 for ARM" or "IAR Assembler V4.11.1.4666 for Renesas RX"
@@ -137,6 +138,19 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
if(_all_compileid_matches)
list(GET _all_compileid_matches "-1" CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID)
endif()
+ elseif("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xClang")
+ # Test whether an MSVC-like command-line option works.
+ execute_process(COMMAND ${CMAKE_ASM${ASM_DIALECT}_COMPILER} -?
+ OUTPUT_VARIABLE _clang_output
+ ERROR_VARIABLE _clang_output
+ RESULT_VARIABLE _clang_result)
+ if(_clang_result EQUAL 0)
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "MSVC")
+ set(CMAKE_ASM${ASM_DIALECT}_SIMULATE_ID MSVC)
+ else()
+ set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "GNU")
+ endif()
+ set(_variant " with ${CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT}-like command-line")
endif()
_cmake_find_compiler_sysroot(ASM${ASM_DIALECT})
@@ -144,6 +158,8 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
unset(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_OUTPUT)
unset(_all_compileid_matches)
unset(_compileid)
+ unset(_clang_result)
+ unset(_clang_output)
endif()
if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
@@ -157,9 +173,10 @@ if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID)
else()
set(_archid "")
endif()
- message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}")
+ message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}${_variant}")
unset(_archid)
unset(_version)
+ unset(_variant)
else()
message(STATUS "The ASM${ASM_DIALECT} compiler identification is unknown")
endif()
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index 0f80f9cff..15eab0f5e 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -128,11 +128,6 @@ if(NOT CMAKE_C_COMPILER_ID_RUN)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(CMAKE_COMPILER_IS_GNUCC 1)
endif()
- if(CMAKE_C_PLATFORM_ID MATCHES "MinGW")
- set(CMAKE_COMPILER_IS_MINGW 1)
- elseif(CMAKE_C_PLATFORM_ID MATCHES "Cygwin")
- set(CMAKE_COMPILER_IS_CYGWIN 1)
- endif()
else()
if(NOT DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT)
# Some toolchain files set our internal CMAKE_C_COMPILER_ID_RUN
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index e360d3127..d06315e47 100644
--- a/Modules/CMakeDetermineCUDACompiler.cmake
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -192,17 +192,31 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${_CUDA_NVCC_EXECUTABLE}" DIRECTORY)
get_filename_component(CMAKE_CUDA_COMPILER_TOOLKIT_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}" DIRECTORY)
endif()
+
+ if(_CUDA_NVCC_OUT MATCHES "\\#\\$ NVVMIR_LIBRARY_DIR=([^\r\n]*)")
+ get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${CMAKE_MATCH_1}" ABSOLUTE)
+
+ #We require the path to end in `/nvvm/libdevice'
+ if(_CUDA_NVVMIR_LIBRARY_DIR MATCHES "nvvm/libdevice$")
+ get_filename_component(_CUDA_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}/../.." ABSOLUTE)
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR "${_CUDA_NVVMIR_LIBRARY_DIR}")
+ endif()
+
+ unset(_CUDA_NVVMIR_LIBRARY_DIR)
+ unset(_cuda_nvvmir_dir_name)
+ endif()
unset(_CUDA_NVCC_OUT)
set(CMAKE_CUDA_DEVICE_LINKER "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/nvlink${CMAKE_EXECUTABLE_SUFFIX}")
set(CMAKE_CUDA_FATBINARY "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/bin/fatbinary${CMAKE_EXECUTABLE_SUFFIX}")
-
# In a non-scattered installation the following are equivalent to CMAKE_CUDA_COMPILER_TOOLKIT_ROOT.
# We first check for a non-scattered installation to prefer it over a scattered installation.
# CMAKE_CUDA_COMPILER_LIBRARY_ROOT contains the device library.
- if(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvvm/libdevice")
+ if(DEFINED CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR)
+ set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR}")
+ elseif(EXISTS "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/nvvm/libdevice")
set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}")
elseif(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/cuda/nvvm/libdevice")
set(CMAKE_CUDA_COMPILER_LIBRARY_ROOT "${CMAKE_SYSROOT_LINK}/usr/lib/cuda")
@@ -211,6 +225,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
else()
message(FATAL_ERROR "Couldn't find CUDA library root.")
endif()
+ unset(CMAKE_CUDA_COMPILER_LIBRARY_ROOT_FROM_NVVMIR_LIBRARY_DIR)
# CMAKE_CUDA_COMPILER_TOOLKIT_LIBRARY_ROOT contains the linking stubs necessary for device linking and other low-level library files.
if(CMAKE_SYSROOT_LINK AND EXISTS "${CMAKE_SYSROOT_LINK}/usr/lib/nvidia-cuda-toolkit/bin/crt/link.stub")
@@ -426,9 +441,10 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
if("${_nvcc_output_line}" MATCHES "^ *nvlink")
string(APPEND _nvcc_log " ignoring nvlink line\n")
elseif(_nvcc_libraries)
- if("${_nvcc_output_line}" MATCHES "(@\"?tmp/a\\.exe\\.res\"?)")
+ if("${_nvcc_output_line}" MATCHES "(@\"?((tmp/)?a\\.exe\\.res)\"?)")
set(_nvcc_link_res_arg "${CMAKE_MATCH_1}")
- set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/tmp/a.exe.res")
+ set(_nvcc_link_res_file "${CMAKE_MATCH_2}")
+ set(_nvcc_link_res "${CMAKE_PLATFORM_INFO_DIR}/CompilerIdCUDA/${_nvcc_link_res_file}")
if(EXISTS "${_nvcc_link_res}")
file(READ "${_nvcc_link_res}" _nvcc_link_res_content)
string(REPLACE "${_nvcc_link_res_arg}" "${_nvcc_link_res_content}" _nvcc_output_line "${_nvcc_output_line}")
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index 556518f49..72dc8d3d5 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -125,11 +125,6 @@ if(NOT CMAKE_CXX_COMPILER_ID_RUN)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_COMPILER_IS_GNUCXX 1)
endif()
- if(CMAKE_CXX_PLATFORM_ID MATCHES "MinGW")
- set(CMAKE_COMPILER_IS_MINGW 1)
- elseif(CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin")
- set(CMAKE_COMPILER_IS_CYGWIN 1)
- endif()
else()
if(NOT DEFINED CMAKE_CXX_COMPILER_FRONTEND_VARIANT)
# Some toolchain files set our internal CMAKE_CXX_COMPILER_ID_RUN
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index e564517c0..c62cb7d24 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -267,6 +267,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
+ set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
endfunction()
@@ -319,13 +320,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
set(id_cl "$(CLToolExe)")
elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
set(id_cl clang.exe)
+ # Executable names have been chosen according documentation
+ # URL: (https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-dpcpp-compiler/top.html#top_GUID-A9B4C91D-97AC-450D-9742-9D895BC8AEE1)
elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "DPC\\+\\+ Compiler")
set(id_cl dpcpp.exe)
- elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler ([8-9]\\.|1[0-9]\\.|XE)")
- set(id_cl icl.exe)
- elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler")
+ elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler 2021")
set(id_cl icx.exe)
+ elseif(CMAKE_VS_PLATFORM_TOOLSET MATCHES "C\\+\\+ Compiler")
+ set(id_cl icl.exe)
endif()
else()
set(id_cl cl.exe)
@@ -418,6 +421,15 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
if(CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR)
set(id_ToolsetVCTargetsDir "<VCTargetsPath>${CMAKE_VS_PLATFORM_TOOLSET_VCTARGETS_CUSTOM_DIR}</VCTargetsPath>")
endif()
+ if(CMAKE_VS_TARGET_FRAMEWORK_VERSION)
+ set(id_TargetFrameworkVersion "<TargetFrameworkVersion>${CMAKE_VS_TARGET_FRAMEWORK_VERSION}</TargetFrameworkVersion>")
+ endif()
+ if(CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER)
+ set(id_TargetFrameworkIdentifier "<TargetFrameworkIdentifier>${CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER}</TargetFrameworkIdentifier>")
+ endif()
+ if(CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION)
+ set(id_TargetFrameworkTargetsVersion "<TargetFrameworkTargetsVersion>${CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION}</TargetFrameworkTargetsVersion>")
+ endif()
set(id_CustomGlobals "")
foreach(pair IN LISTS CMAKE_VS_GLOBALS)
if("${pair}" MATCHES "([^=]+)=(.*)$")
@@ -536,7 +548,8 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
else()
set(id_toolset "")
endif()
- if("${lang}" STREQUAL "Swift")
+ set(id_lang_version "")
+ if("x${lang}" STREQUAL "xSwift")
if(CMAKE_Swift_LANGUAGE_VERSION)
set(id_lang_version "SWIFT_VERSION = ${CMAKE_Swift_LANGUAGE_VERSION};")
elseif(XCODE_VERSION VERSION_GREATER_EQUAL 10.2)
@@ -546,8 +559,14 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
else()
set(id_lang_version "SWIFT_VERSION = 2.3;")
endif()
- else()
- set(id_lang_version "")
+ elseif("x${lang}" STREQUAL "xC" OR "x${lang}" STREQUAL "xOBJC")
+ if(CMAKE_${lang}_COMPILER_ID_FLAGS MATCHES "(^| )(-std=[^ ]+)( |$)")
+ set(id_lang_version "OTHER_CFLAGS = \"${CMAKE_MATCH_2}\";")
+ endif()
+ elseif("x${lang}" STREQUAL "xCXX" OR "x${lang}" STREQUAL "xOBJCXX")
+ if(CMAKE_${lang}_COMPILER_ID_FLAGS MATCHES "(^| )(-std=[^ ]+)( |$)")
+ set(id_lang_version "OTHER_CPLUSPLUSFLAGS = \"${CMAKE_MATCH_2}\";")
+ endif()
endif()
if(CMAKE_OSX_DEPLOYMENT_TARGET)
set(id_deployment_target
@@ -685,7 +704,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
# Check the result of compilation.
if(CMAKE_${lang}_COMPILER_ID_RESULT
# Intel Fortran warns and ignores preprocessor lines without /fpp
- OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "Bad # preprocessor line"
+ OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line"
)
# Compilation failed.
set(MSG
@@ -696,7 +715,10 @@ ${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}
")
- file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
+ # Log the output unless we recognize it as a known-bad case.
+ if(NOT CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
+ endif()
# Some languages may know the correct/desired set of flags and want to fail right away if they don't work.
# This is currently only used by CUDA.
@@ -876,9 +898,12 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
if("${info}" MATCHES "INFO:qnxnto\\[\\]")
set(COMPILER_QNXNTO 1)
endif()
- if("${info}" MATCHES "INFO:dialect_default\\[([^]\"]*)\\]")
+ if("${info}" MATCHES "INFO:standard_default\\[([^]\"]*)\\]")
set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_MATCH_1}")
endif()
+ if("${info}" MATCHES "INFO:extensions_default\\[([^]\"]*)\\]")
+ set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_MATCH_1}")
+ endif()
endforeach()
# Construct compiler version from components if needed.
@@ -988,6 +1013,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE)
set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
+ set(CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT "${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT}" PARENT_SCOPE)
endfunction()
#-----------------------------------------------------------------------------
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index d7d032c01..6a8984b2b 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -235,11 +235,6 @@ if(NOT CMAKE_Fortran_COMPILER_ID_RUN)
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
set(CMAKE_COMPILER_IS_GNUG77 1)
endif()
- if(CMAKE_Fortran_PLATFORM_ID MATCHES "MinGW")
- set(CMAKE_COMPILER_IS_MINGW 1)
- elseif(CMAKE_Fortran_PLATFORM_ID MATCHES "Cygwin")
- set(CMAKE_COMPILER_IS_CYGWIN 1)
- endif()
endif()
if (NOT _CMAKE_TOOLCHAIN_LOCATION)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index 84fde49ce..6c81754d3 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -82,8 +82,7 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xClang")
set(_CMAKE_NM_NAMES "llvm-nm" "nm")
list(PREPEND _CMAKE_AR_NAMES "llvm-lib")
- # llvm-mt does not support all flags we need in vs_link_exe
- # list(PREPEND _CMAKE_MT_NAMES "llvm-mt")
+ list(PREPEND _CMAKE_MT_NAMES "llvm-mt")
list(PREPEND _CMAKE_LINKER_NAMES "lld-link")
list(APPEND _CMAKE_TOOL_VARS NM)
elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xIntel")
@@ -118,7 +117,7 @@ elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^xIAR$")
endfunction()
__resolve_IAR_hints("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" _CMAKE_TOOLCHAIN_LOCATION)
- set(_CMAKE_IAR_ITOOLS "ARM" "RX" "RH850" "RL78" "RISCV" "STM8")
+ set(_CMAKE_IAR_ITOOLS "ARM" "RX" "RH850" "RL78" "RISCV" "RISC-V" "STM8")
set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051")
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS)
@@ -173,15 +172,7 @@ else()
else()
list(PREPEND _CMAKE_LINKER_NAMES "ld.lld")
endif()
- if(APPLE)
- # llvm-ar does not generate a symbol table that the Apple ld64 linker accepts.
- # FIXME(#23333): We still need to consider 'llvm-ar' as a fallback because
- # the 'APPLE' definition may be based on the host in this context, and a
- # cross-compiling toolchain may not have 'ar'.
- list(APPEND _CMAKE_AR_NAMES "llvm-ar")
- else()
- list(PREPEND _CMAKE_AR_NAMES "llvm-ar")
- endif()
+ list(PREPEND _CMAKE_AR_NAMES "llvm-ar")
list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib")
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}" VERSION_GREATER_EQUAL 11)
# llvm-strip versions prior to 11 require additional flags we do not yet add.
diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake
index 815dfc90d..726e2a292 100644
--- a/Modules/CMakeFindPackageMode.cmake
+++ b/Modules/CMakeFindPackageMode.cmake
@@ -78,7 +78,7 @@ if(UNIX)
# from the outside
if(NOT CMAKE_SIZEOF_VOID_P)
set(CMAKE_SIZEOF_VOID_P 4)
- if(EXISTS /usr/lib64)
+ if(EXISTS ${CMAKE_SYSROOT}/usr/lib64)
set(CMAKE_SIZEOF_VOID_P 8)
else()
# use the file utility to check whether itself is 64 bit:
diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index d474f9644..97f891e19 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -19,20 +19,11 @@ set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@)
set(CMAKE_Fortran_COMPILER_LOADED 1)
set(CMAKE_Fortran_COMPILER_WORKS @CMAKE_Fortran_COMPILER_WORKS@)
set(CMAKE_Fortran_ABI_COMPILED @CMAKE_Fortran_ABI_COMPILED@)
-set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@)
-set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@)
-if(CMAKE_COMPILER_IS_CYGWIN)
- set(CYGWIN 1)
- set(UNIX 1)
-endif()
set(CMAKE_Fortran_COMPILER_ENV_VAR "FC")
set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 @CMAKE_Fortran_COMPILER_SUPPORTS_F90@)
-if(CMAKE_COMPILER_IS_MINGW)
- set(MINGW 1)
-endif()
set(CMAKE_Fortran_COMPILER_ID_RUN 1)
set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95)
set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
diff --git a/Modules/CMakeFortranCompilerABI.F90 b/Modules/CMakeFortranCompilerABI.F90
new file mode 100644
index 000000000..4a1715331
--- /dev/null
+++ b/Modules/CMakeFortranCompilerABI.F90
@@ -0,0 +1,48 @@
+program CMakeFortranCompilerABI
+
+implicit none
+
+integer :: i(1) = 0
+where (i==0) i=1
+if (any(i/=1)) stop 1
+! showing Fortran 90 syntax is OK
+
+#if 0
+! Address Size
+#endif
+#if defined(_LP64)
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(_M_IA64)
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(_M_X64)
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(_M_AMD64)
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(__x86_64__)
+PRINT *, 'INFO:sizeof_dptr[8]'
+
+#elif defined(_ILP32)
+PRINT *, 'INFO:sizeof_dptr[4]'
+#elif defined(_M_IX86)
+PRINT *, 'INFO:sizeof_dptr[4]'
+#elif defined(__i386__)
+PRINT *, 'INFO:sizeof_dptr[4]'
+
+#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 4
+PRINT *, 'INFO:sizeof_dptr[4]'
+#elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ == 8
+PRINT *, 'INFO:sizeof_dptr[8]'
+#elif defined(__SIZEOF_SIZE_T__) && __SIZEOF_SIZE_T__ == 4
+PRINT *, 'INFO:sizeof_dptr[4]'
+#endif
+
+#if 0
+! Application Binary Interface
+#endif
+#if defined(__ELF__)
+PRINT *, 'INFO:abi[ELF]'
+#endif
+PRINT *, 'ABI Detection'
+end program
diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake
index 9a4ce6357..0f71c6f04 100644
--- a/Modules/CMakeFortranInformation.cmake
+++ b/Modules/CMakeFortranInformation.cmake
@@ -157,6 +157,15 @@ if(NOT CMAKE_INCLUDE_FLAG_Fortran)
set(CMAKE_INCLUDE_FLAG_Fortran ${CMAKE_INCLUDE_FLAG_C})
endif()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_Fortran_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_Fortran_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE BOOL "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo.")
set(CMAKE_Fortran_FLAGS_INIT "$ENV{FFLAGS} ${CMAKE_Fortran_FLAGS_INIT}")
diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in
index 17633a86c..ce4e2cf65 100644
--- a/Modules/CMakeHIPCompiler.cmake.in
+++ b/Modules/CMakeHIPCompiler.cmake.in
@@ -2,6 +2,7 @@ set(CMAKE_HIP_COMPILER "@CMAKE_HIP_COMPILER@")
set(CMAKE_HIP_COMPILER_ID "@CMAKE_HIP_COMPILER_ID@")
set(CMAKE_HIP_COMPILER_VERSION "@CMAKE_HIP_COMPILER_VERSION@")
set(CMAKE_HIP_STANDARD_COMPUTED_DEFAULT "@CMAKE_HIP_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_HIP_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_HIP_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_HIP_COMPILE_FEATURES "@CMAKE_HIP_COMPILE_FEATURES@")
set(CMAKE_HIP98_COMPILE_FEATURES "@CMAKE_HIP03_COMPILE_FEATURES@")
set(CMAKE_HIP11_COMPILE_FEATURES "@CMAKE_HIP11_COMPILE_FEATURES@")
diff --git a/Modules/CMakeHIPCompilerId.hip.in b/Modules/CMakeHIPCompilerId.hip.in
index 5258efba0..3c4a1d4be 100644
--- a/Modules/CMakeHIPCompilerId.hip.in
+++ b/Modules/CMakeHIPCompilerId.hip.in
@@ -16,7 +16,7 @@ char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
@CMAKE_HIP_COMPILER_ID_PLATFORM_CONTENT@
@CMAKE_HIP_COMPILER_ID_ERROR_FOR_TEST@
-const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+const char* info_language_standard_default = "INFO" ":" "standard_default["
#if __cplusplus > 202002L
"23"
#elif __cplusplus > 201703L
@@ -32,6 +32,14 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default["
#endif
"]";
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
@@ -48,7 +56,8 @@ int main(int argc, char* argv[])
#ifdef SIMULATE_VERSION_MAJOR
require += info_simulate_version[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake
index 28c5f184a..4c5767767 100644
--- a/Modules/CMakeHIPInformation.cmake
+++ b/Modules/CMakeHIPInformation.cmake
@@ -68,6 +68,15 @@ if(NOT CMAKE_MODULE_EXISTS)
set(CMAKE_SHARED_MODULE_CREATE_HIP_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_HIP_FLAGS})
endif()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_HIP_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_HIP_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
# add the flags to the cache based
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
index ab67bf396..36f6ec150 100644
--- a/Modules/CMakeOBJCCompiler.cmake.in
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -5,6 +5,7 @@ set(CMAKE_OBJC_COMPILER_VERSION "@CMAKE_OBJC_COMPILER_VERSION@")
set(CMAKE_OBJC_COMPILER_VERSION_INTERNAL "@CMAKE_OBJC_COMPILER_VERSION_INTERNAL@")
set(CMAKE_OBJC_COMPILER_WRAPPER "@CMAKE_OBJC_COMPILER_WRAPPER@")
set(CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJC_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_OBJC_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@")
set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@")
set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@")
diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in
index 418fd4852..89bfe02e6 100644
--- a/Modules/CMakeOBJCCompilerId.m.in
+++ b/Modules/CMakeOBJCCompilerId.m.in
@@ -23,23 +23,31 @@ char const* qnxnto = "INFO" ":" "qnxnto[]";
#if !defined(__STDC__)
# if (defined(_MSC_VER) && !defined(__clang__)) \
|| (defined(__ibmxl__) || defined(__IBMC__))
-# define C_DIALECT "90"
+# define C_VERSION "90"
# else
-# define C_DIALECT
+# define C_VERSION
# endif
#elif __STDC_VERSION__ > 201710L
-# define C_DIALECT "23"
+# define C_VERSION "23"
#elif __STDC_VERSION__ >= 201710L
-# define C_DIALECT "17"
+# define C_VERSION "17"
#elif __STDC_VERSION__ >= 201000L
-# define C_DIALECT "11"
+# define C_VERSION "11"
#elif __STDC_VERSION__ >= 199901L
-# define C_DIALECT "99"
+# define C_VERSION "99"
#else
-# define C_DIALECT "90"
+# define C_VERSION "90"
#endif
-const char* info_language_dialect_default =
- "INFO" ":" "dialect_default[" C_DIALECT "]";
+const char* info_language_standard_default =
+ "INFO" ":" "standard_default[" C_VERSION "]";
+
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
/*--------------------------------------------------------------------------*/
@@ -61,7 +69,8 @@ int main(int argc, char* argv[])
#ifdef SIMULATE_VERSION_MAJOR
require += info_simulate_version[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake
index ac67d013c..4c697da3d 100644
--- a/Modules/CMakeOBJCInformation.cmake
+++ b/Modules/CMakeOBJCInformation.cmake
@@ -91,6 +91,15 @@ if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC "${_override}")
endif()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_OBJC_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_OBJC_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
index a24582b8b..4f271003a 100644
--- a/Modules/CMakeOBJCXXCompiler.cmake.in
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -5,6 +5,7 @@ set(CMAKE_OBJCXX_COMPILER_VERSION "@CMAKE_OBJCXX_COMPILER_VERSION@")
set(CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL "@CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL@")
set(CMAKE_OBJCXX_COMPILER_WRAPPER "@CMAKE_OBJCXX_COMPILER_WRAPPER@")
set(CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJCXX_EXTENSIONS_COMPUTED_DEFAULT "@CMAKE_OBJCXX_EXTENSIONS_COMPUTED_DEFAULT@")
set(CMAKE_OBJCXX_COMPILE_FEATURES "@CMAKE_OBJCXX_COMPILE_FEATURES@")
set(CMAKE_OBJCXX98_COMPILE_FEATURES "@CMAKE_OBJCXX98_COMPILE_FEATURES@")
set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@")
diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in
index e2ac35d05..2145b4046 100644
--- a/Modules/CMakeOBJCXXCompilerId.mm.in
+++ b/Modules/CMakeOBJCXXCompilerId.mm.in
@@ -29,7 +29,7 @@ char const* qnxnto = "INFO" ":" "qnxnto[]";
#define CXX_STD __cplusplus
#endif
-const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+const char* info_language_standard_default = "INFO" ":" "standard_default["
#if CXX_STD > 202002L
"23"
#elfif CXX_STD > 201703L
@@ -45,6 +45,14 @@ const char* info_language_dialect_default = "INFO" ":" "dialect_default["
#endif
"]";
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+#if (defined(__clang__) || defined(__GNUC__)) && !defined(__STRICT_ANSI__)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
@@ -64,7 +72,8 @@ int main(int argc, char* argv[])
#ifdef SIMULATE_VERSION_MAJOR
require += info_simulate_version[argc];
#endif
- require += info_language_dialect_default[argc];
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
(void)argv;
return require;
}
diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake
index 70e8579a9..a6d824f10 100644
--- a/Modules/CMakeOBJCXXInformation.cmake
+++ b/Modules/CMakeOBJCXXInformation.cmake
@@ -189,6 +189,15 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
endif()
endforeach()
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_OBJCXX_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_OBJCXX_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
# add the flags to the cache based
# on the initial values computed in the platform/*.cmake files
# use _INIT variables so that this only happens the first time
diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake
index 8f0909c99..ecad1d51e 100644
--- a/Modules/CMakeSwiftInformation.cmake
+++ b/Modules/CMakeSwiftInformation.cmake
@@ -70,6 +70,15 @@ set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
+if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+ if(NOT DEFINED CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG)
+ set(CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG "LINKER:--no-as-needed")
+ endif()
+ if(NOT DEFINED CMAKE_LINK_WHAT_YOU_USE_CHECK)
+ set(CMAKE_LINK_WHAT_YOU_USE_CHECK ldd -u -r)
+ endif()
+endif()
+
cmake_initialize_per_config_variable(CMAKE_Swift_FLAGS "Swift Compiler Flags")
# NOTE(compnerd) we do not have an object compile rule since we build the objects as part of the link step
diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake
index f25788df4..579f83ff8 100644
--- a/Modules/CMakeTestFortranCompiler.cmake
+++ b/Modules/CMakeTestFortranCompiler.cmake
@@ -17,11 +17,18 @@ unset(CMAKE_Fortran_COMPILER_WORKS CACHE)
# Try to identify the ABI and configure it into CMakeFortranCompiler.cmake
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
-CMAKE_DETERMINE_COMPILER_ABI(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F)
+CMAKE_DETERMINE_COMPILER_ABI(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F90)
if(CMAKE_Fortran_ABI_COMPILED)
# The compiler worked so skip dedicated test below.
set(CMAKE_Fortran_COMPILER_WORKS TRUE)
+ set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 1)
message(STATUS "Check for working Fortran compiler: ${CMAKE_Fortran_COMPILER} - skipped")
+else()
+ cmake_determine_compiler_abi(Fortran ${CMAKE_ROOT}/Modules/CMakeFortranCompilerABI.F)
+ if(CMAKE_Fortran_ABI_COMPILED)
+ set(CMAKE_Fortran_COMPILER_WORKS TRUE)
+ message(STATUS "Check for working Fortran 77 compiler: ${CMAKE_Fortran_COMPILER} - skipped")
+ endif()
endif()
# This file is used by EnableLanguage in cmGlobalGenerator to
diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake
index 5acd80624..ecbfa7fc2 100644
--- a/Modules/CMakeTestHIPCompiler.cmake
+++ b/Modules/CMakeTestHIPCompiler.cmake
@@ -10,7 +10,7 @@ if(CMAKE_HIP_COMPILER_FORCED)
endif()
set(__CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS}")
-string(APPEND CMAKE_HIP_FLAGS "--cuda-host-only")
+string(APPEND CMAKE_HIP_FLAGS " --cuda-host-only")
include(CMakeTestCompilerCommon)
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index 2e68770a5..85108db41 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -439,6 +439,7 @@ set(_CPACK_IFW_PREFIXES
"QtIFW-")
set(_CPACK_IFW_VERSIONS
+ "4.2"
"4.1"
"4.0"
"3.2"
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index b4da4fac8..7b13c3aa3 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -25,7 +25,7 @@ Check if a symbol exists as a function, variable, or macro in ``C++``.
as a function or variable then the symbol must also be available for
linking. If the symbol is a type, enum value, or C++ template it will
not be recognized: consider using the :module:`CheckTypeSize`
- or :module:`CheckCXXSourceCompiles` module instead.
+ or :module:`CheckSourceCompiles` module instead.
.. note::
diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake
index ad72e2f09..8f1ca9dd3 100644
--- a/Modules/CheckFortranFunctionExists.cmake
+++ b/Modules/CheckFortranFunctionExists.cmake
@@ -20,6 +20,12 @@ Check if a Fortran function exists.
``<result>``
variable to store the result; will be created as an internal cache variable.
+.. note::
+
+ This command does not detect functions in Fortran modules. In general it is
+ recommended to use :module:`CheckSourceCompiles` instead to determine if a
+ Fortran function or subroutine is available.
+
The following variables may be set before calling this macro to modify
the way the check is run:
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 559c103e8..52f707c00 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -46,7 +46,7 @@ macro(check_language lang)
file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang})
set(extra_compiler_variables)
- if(${lang} STREQUAL CUDA)
+ if(${lang} STREQUAL CUDA AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
set(extra_compiler_variables "set(CMAKE_CUDA_HOST_COMPILER \\\"\${CMAKE_CUDA_HOST_COMPILER}\\\")")
endif()
diff --git a/Modules/CheckLinkerFlag.cmake b/Modules/CheckLinkerFlag.cmake
index 28ac2e32e..e85e43e9b 100644
--- a/Modules/CheckLinkerFlag.cmake
+++ b/Modules/CheckLinkerFlag.cmake
@@ -41,6 +41,10 @@ include_guard(GLOBAL)
include(CMakeCheckCompilerFlagCommonPatterns)
+cmake_policy(PUSH)
+cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
+cmake_policy(SET CMP0057 NEW) # if() supports IN_LIST
+
function(CHECK_LINKER_FLAG _lang _flag _var)
get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
if (NOT _lang IN_LIST _supported_languages)
@@ -82,3 +86,5 @@ function(CHECK_LINKER_FLAG _lang _flag _var)
endforeach()
set(${_var} "${${_var}}" PARENT_SCOPE)
endfunction()
+
+cmake_policy(POP)
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index f8ca58402..48ee3c477 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -24,7 +24,7 @@ available and assumed to work. If the header files declare the symbol
as a function or variable then the symbol must also be available for
linking (so intrinsics may not be detected).
If the symbol is a type, enum value, or intrinsic it will not be recognized
-(consider using :module:`CheckTypeSize` or :module:`CheckCSourceCompiles`).
+(consider using :module:`CheckTypeSize` or :module:`CheckSourceCompiles`).
If the check needs to be done in C++, consider using
:module:`CheckCXXSymbolExists` instead.
diff --git a/Modules/Compiler/ARMClang-C.cmake b/Modules/Compiler/ARMClang-C.cmake
index 0a64a8a4f..01c4cea08 100644
--- a/Modules/Compiler/ARMClang-C.cmake
+++ b/Modules/Compiler/ARMClang-C.cmake
@@ -2,6 +2,14 @@ include(Compiler/Clang-C)
include(Compiler/ARMClang)
__compiler_armclang(C)
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_C)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_C_DEPFILE_FORMAT gcc)
+ set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
+endif()
+
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
diff --git a/Modules/Compiler/ARMClang-CXX.cmake b/Modules/Compiler/ARMClang-CXX.cmake
index 5dfb4011e..045b78311 100644
--- a/Modules/Compiler/ARMClang-CXX.cmake
+++ b/Modules/Compiler/ARMClang-CXX.cmake
@@ -1,3 +1,11 @@
include(Compiler/Clang-CXX)
include(Compiler/ARMClang)
__compiler_armclang(CXX)
+
+if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
+ AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
+ AND CMAKE_DEPFILE_FLAGS_CXX)
+ # dependencies are computed by the compiler itself
+ set(CMAKE_CXX_DEPFILE_FORMAT gcc)
+ set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
+endif()
diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake
index 7c979697a..28be1dfd5 100644
--- a/Modules/Compiler/AppleClang-CXX.cmake
+++ b/Modules/Compiler/AppleClang-CXX.cmake
@@ -47,17 +47,9 @@ if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON)
endif()
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
- set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++20")
- set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++20")
-elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
+if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
endif()
-if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0)
- set(CMAKE_CXX23_STANDARD_COMPILE_OPTION "-std=c++2b")
- set(CMAKE_CXX23_EXTENSION_COMPILE_OPTION "-std=gnu++2b")
-endif()
-
__compiler_check_default_language_standard(CXX 4.0 98)
diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
index c86af98f8..2f220d466 100644
--- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake
+++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake
@@ -38,20 +38,26 @@ macro(__compiler_check_default_language_standard lang stdver1 std1)
# support for language standards, then don't bother.
if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL "${stdver1}")
if (NOT CMAKE_${lang}_COMPILER_FORCED)
- if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT)
- message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}")
+ if (NOT CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT OR NOT DEFINED CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT)
+ message(FATAL_ERROR "CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT and CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT should be set for ${CMAKE_${lang}_COMPILER_ID} (${CMAKE_${lang}_COMPILER}) version ${CMAKE_${lang}_COMPILER_VERSION}")
endif ()
set(CMAKE_${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT})
+ set(CMAKE_${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_COMPUTED_DEFAULT})
else ()
list(REVERSE __std_ver_pairs)
foreach (__std_ver_pair IN LISTS __std_ver_pairs)
string(REGEX MATCH "([^ ]+) (.+)" __std_ver_pair "${__std_ver_pair}")
set(__stdver ${CMAKE_MATCH_1})
set(__std ${CMAKE_MATCH_2})
- if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver AND
- NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT)
- # Compiler id was forced so just guess the default standard level.
- set(CMAKE_${lang}_STANDARD_DEFAULT ${__std})
+ # Compiler id was forced so just guess the defaults.
+ if (CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL __stdver)
+ if(NOT DEFINED CMAKE_${lang}_EXTENSIONS_DEFAULT)
+ # Currently known compilers default to enabling extensions.
+ set(CMAKE_${lang}_EXTENSIONS_DEFAULT ON)
+ endif()
+ if(NOT DEFINED CMAKE_${lang}_STANDARD_DEFAULT)
+ set(CMAKE_${lang}_STANDARD_DEFAULT ${__std})
+ endif()
endif ()
unset(__std)
unset(__stdver)
diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake
index cf493d720..1b765ad14 100644
--- a/Modules/Compiler/Clang-C.cmake
+++ b/Modules/Compiler/Clang-C.cmake
@@ -9,6 +9,7 @@ endif()
if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
AND CMAKE_DEPFILE_FLAGS_C)
diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake
index 98828e011..84b05d7f0 100644
--- a/Modules/Compiler/Clang-CXX.cmake
+++ b/Modules/Compiler/Clang-CXX.cmake
@@ -22,6 +22,7 @@ endif()
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
AND CMAKE_GENERATOR MATCHES "Makefiles"
AND CMAKE_DEPFILE_FLAGS_CXX)
diff --git a/Modules/Compiler/IAR-ASM.cmake b/Modules/Compiler/IAR-ASM.cmake
index e3ca16edc..bae0fbd8c 100644
--- a/Modules/Compiler/IAR-ASM.cmake
+++ b/Modules/Compiler/IAR-ASM.cmake
@@ -1,57 +1,45 @@
-# This file is processed when the IAR compiler is used for an assembler file
+# This file is processed when the IAR Assembler is used
include(Compiler/IAR)
-if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+set(_CMAKE_IAR_ITOOLS "ARM" "RH850" "RL78" "RX" "RISC-V" "STM8")
+set(_CMAKE_IAR_XTOOLS "AVR" "MSP430" "V850" "8051")
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
-
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
-
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISC-V")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+set(_CMAKE_IAR_ASM_SILENT "RH850" "RL78" "RX" "RISC-V" "STM8")
+if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ASM_SILENT)
+ set(_CMAKE_IAR_SILENCER_FLAG " --silent")
+else()
+ set(_CMAKE_IAR_SILENCER_FLAG " -S")
+endif()
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_xlink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;asm;msa)
+string(APPEND CMAKE_ASM_FLAGS_INIT " ")
+string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r")
+string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
+string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "MSP430")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_xlink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s43;asm;msa)
+set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> ${_CMAKE_IAR_SILENCER_FLAG} <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "V850")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_xlink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s85;asm;msa)
+if("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_ITOOLS)
+ __compiler_iar_ilink(ASM)
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa;S)
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "8051")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -S <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
+elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" IN_LIST _CMAKE_IAR_XTOOLS)
__compiler_iar_xlink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s51;asm;msa)
-
-elseif("${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID}" STREQUAL "STM8")
- set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
- __compiler_iar_ilink(ASM)
- set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;asm;msa)
+ # AVR=s90, MSP430=s43, V850=s85, 8051=s51
+ set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s90;s43;s85;s51;asm;msa)
else()
message(FATAL_ERROR "CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID not detected. This should be automatic.")
+
endif()
+
+unset(_CMAKE_IAR_ITOOLS)
+unset(_CMAKE_IAR_XTOOLS)
+unset(_CMAKE_IAR_ASM_SILENT)
+unset(_CMAKE_IAR_SILENCER_FLAG)
+
+cmake_policy(POP)
diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake
index 054ee74c1..0ef1a2a85 100644
--- a/Modules/Compiler/IAR-C.cmake
+++ b/Modules/Compiler/IAR-C.cmake
@@ -1,54 +1,61 @@
-# This file is processed when the IAR compiler is used for a C file
-
+# This file is processed when the IAR C Compiler is used
+#
+# C Language Specification support
+# - Newer versions of the IAR C Compiler require the --c89 flag to build a file under the C90 standard.
+# - Earlier versions of the compiler had C90 by default, not requiring the backward-compatibility flag.
+#
+# The IAR Language Extensions
+# - The IAR Language Extensions can be enabled by -e flag
+#
include(Compiler/IAR)
include(Compiler/CMakeCommonCompilerMacros)
-# Common
-if(NOT CMAKE_C_COMPILER_VERSION)
+if(NOT DEFINED CMAKE_C_COMPILER_VERSION)
message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION not detected. This should be automatic.")
endif()
+# Unused after CMP0128
set(CMAKE_C_EXTENSION_COMPILE_OPTION -e)
if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 7)
set(CMAKE_C90_STANDARD_COMPILE_OPTION --c89)
set(CMAKE_C90_EXTENSION_COMPILE_OPTION --c89 -e)
- set(CMAKE_C99_STANDARD_COMPILE_OPTION "")
- set(CMAKE_C99_EXTENSION_COMPILE_OPTION -e)
else()
set(CMAKE_C90_STANDARD_COMPILE_OPTION "")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION -e)
endif()
-if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 8)
- set(CMAKE_C11_STANDARD_COMPILE_OPTION "")
- set(CMAKE_C11_EXTENSION_COMPILE_OPTION -e)
-endif()
+set(CMAKE_C${CMAKE_C_STANDARD_COMPUTED_DEFAULT}_STANDARD_COMPILE_OPTION "")
+set(CMAKE_C${CMAKE_C_STANDARD_COMPUTED_DEFAULT}_EXTENSION_COMPILE_OPTION -e)
# Architecture specific
if("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM")
- if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_LESS 7)
- # IAR ARM 4.X uses xlink.exe, detection is not yet implemented
- message(FATAL_ERROR "CMAKE_C_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.")
+ if (CMAKE_C_COMPILER_VERSION VERSION_LESS 5)
+ # IAR C Compiler for Arm prior version 5.xx uses XLINK. Support in CMake is not implemented.
+ message(FATAL_ERROR "IAR C Compiler for Arm version ${CMAKE_C_COMPILER_VERSION} not supported by CMake.")
endif()
__compiler_iar_ilink(C)
- __compiler_check_default_language_standard(C 1.10 90 6.10 99 8.10 11)
+ __compiler_check_default_language_standard(C 5.10 90 6.10 99 8.10 11 8.40 17)
elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX")
__compiler_iar_ilink(C)
- __compiler_check_default_language_standard(C 1.10 90 2.10 99 4.10 11)
+ __compiler_check_default_language_standard(C 1.10 90 2.10 99 4.10 11 4.20 17)
elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850")
__compiler_iar_ilink(C)
- __compiler_check_default_language_standard(C 1.10 90 1.10 99 2.10 11)
+ __compiler_check_default_language_standard(C 1.10 90 1.10 99 2.10 11 2.21 17)
elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78")
+ if(CMAKE_C_COMPILER_VERSION VERSION_LESS 2)
+ # IAR C Compiler for RL78 prior version 2.xx uses XLINK. Support in CMake is not implemented.
+ message(FATAL_ERROR "IAR C Compiler for RL78 version ${CMAKE_C_COMPILER_VERSION} not supported by CMake.")
+ endif()
__compiler_iar_ilink(C)
- __compiler_check_default_language_standard(C 1.10 90 1.10 99 4.10 11)
+ __compiler_check_default_language_standard(C 2.10 90 2.10 99 4.10 11 4.20 17)
elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV")
__compiler_iar_ilink(C)
- __compiler_check_default_language_standard(C 1.10 90 1.10 99 1.10 11)
+ __compiler_check_default_language_standard(C 1.10 90 1.10 99 1.10 11 1.21 17)
elseif("${CMAKE_C_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR")
__compiler_iar_xlink(C)
diff --git a/Modules/Compiler/IAR-CXX.cmake b/Modules/Compiler/IAR-CXX.cmake
index d93b27289..a3f1dbc29 100644
--- a/Modules/Compiler/IAR-CXX.cmake
+++ b/Modules/Compiler/IAR-CXX.cmake
@@ -1,63 +1,65 @@
-# This file is processed when the IAR compiler is used for a C++ file
-
+# This file is processed when the IAR C++ Compiler is used
+#
+# C++ Language Specification support
+# - Newer versions of the IAR C++ Compiler require the --c++ flag to build a C++ file.
+# Earlier versions for non-ARM architectures provided Embedded C++, enabled with the --eec++ flag.
+#
+# The IAR Language Extensions
+# - The IAR Language Extensions can be enabled by -e flag
+#
include(Compiler/IAR)
include(Compiler/CMakeCommonCompilerMacros)
-# Common
-if(NOT CMAKE_CXX_COMPILER_VERSION)
+if(NOT DEFINED CMAKE_CXX_COMPILER_VERSION)
message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION not detected. This should be automatic.")
endif()
+# Whenever needed, override this default behavior using CMAKE_IAR_CXX_FLAG in your toolchain file.
if(NOT CMAKE_IAR_CXX_FLAG)
- # The --c++ flag was introduced in platform version 9 for all architectures except ARM where it was introduced already in version 7
- if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 8 OR
- (CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 6 AND "${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM") )
- set(CMAKE_IAR_CXX_FLAG --c++)
+ set(_CMAKE_IAR_MODERNCXX_LIST 14 17)
+ if(${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} IN_LIST _CMAKE_IAR_MODERNCXX_LIST OR
+ ("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM" AND ${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT} EQUAL 98))
+ string(PREPEND CMAKE_CXX_FLAGS "--c++ ")
else()
- set(CMAKE_IAR_CXX_FLAG --eec++)
+ string(PREPEND CMAKE_CXX_FLAGS "--eec++ ")
endif()
+ unset(_CMAKE_IAR_MODERNCXX_LIST)
endif()
-set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e)
+set(CMAKE_CXX_STANDARD_COMPILE_OPTION "")
+set(CMAKE_CXX_EXTENSION_COMPILE_OPTION -e) # Unused after CMP0128
-if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 7)
- set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "")
- set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION -e)
- set(CMAKE_CXX03_STANDARD_COMPILE_OPTION "")
- set(CMAKE_CXX03_EXTENSION_COMPILE_OPTION -e)
-endif()
-
-if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_GREATER 8)
- set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "")
- set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION -e)
- set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "")
- set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION -e)
-endif()
+set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_STANDARD_COMPILE_OPTION "")
+set(CMAKE_CXX${CMAKE_CXX_STANDARD_COMPUTED_DEFAULT}_EXTENSION_COMPILE_OPTION -e)
# Architecture specific
if("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "ARM")
- if(CMAKE_CXX_COMPILER_VERSION_INTERNAL VERSION_LESS 7)
- # IAR ARM 4.X uses xlink.exe, detection is not yet implemented
- message(FATAL_ERROR "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_C_COMPILER_VERSION} not supported by CMake.")
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
+ # IAR C++ Compiler for Arm prior version 5.xx uses XLINK. Support in CMake is not implemented.
+ message(FATAL_ERROR "IAR C++ Compiler for Arm version ${CMAKE_CXX_COMPILER_VERSION} not supported by CMake.")
endif()
__compiler_iar_ilink(CXX)
- __compiler_check_default_language_standard(CXX 6.10 98 8.10 14)
+ __compiler_check_default_language_standard(CXX 5.10 98 8.10 14 8.40 17)
elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RX")
__compiler_iar_ilink(CXX)
- __compiler_check_default_language_standard(CXX 2.10 98 4.10 14)
+ __compiler_check_default_language_standard(CXX 2.10 98 4.10 14 4.20 17)
elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RH850")
__compiler_iar_ilink(CXX)
- __compiler_check_default_language_standard(CXX 1.10 98 2.10 14)
+ __compiler_check_default_language_standard(CXX 1.10 98 2.10 14 2.21 17)
elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RL78")
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2)
+ # # IAR C++ Compiler for RL78 prior version 2.xx uses XLINK. Support in CMake is not implemented.
+ message(FATAL_ERROR "IAR C++ Compiler for RL78 version ${CMAKE_CXX_COMPILER_VERSION} not supported by CMake.")
+ endif()
__compiler_iar_ilink(CXX)
- __compiler_check_default_language_standard(CXX 1.10 98 4.10 14)
+ __compiler_check_default_language_standard(CXX 2.10 98 4.10 14 4.20 17)
elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "RISCV")
__compiler_iar_ilink(CXX)
- __compiler_check_default_language_standard(CXX 1.10 98 1.10 14)
+ __compiler_check_default_language_standard(CXX 1.10 98 1.10 14 1.21 17)
elseif("${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "AVR")
__compiler_iar_xlink(CXX)
diff --git a/Modules/Compiler/IAR-DetermineCompiler.cmake b/Modules/Compiler/IAR-DetermineCompiler.cmake
index 443b09c32..b03fd1faa 100644
--- a/Modules/Compiler/IAR-DetermineCompiler.cmake
+++ b/Modules/Compiler/IAR-DetermineCompiler.cmake
@@ -1,28 +1,26 @@
-# IAR Systems compiler for ARM embedded systems.
-# http://www.iar.com
-# http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf
+# IAR C/C++ Compiler (https://www.iar.com)
+# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX and V850
#
-# __IAR_SYSTEMS_ICC__ An integer that identifies the IAR compiler platform:
-# 9 and higher means C11 and C++14 as language default
-# 8 means C99 and C++03 as language default
-# 7 and lower means C89 and EC++ as language default.
-# __ICCARM__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for ARM
-# __VER__ An integer that identifies the version number of the IAR compiler in use. For example,
-# version 5.11.3 is returned as 5011003.
+# IAR C/C++ Compiler for <arch> internal integer symbols used in CMake:
#
-# IAR Systems Compiler for AVR embedded systems
-# http://supp.iar.com/FilesPublic/UPDINFO/007051/ew/doc/EWAVR_CompilerReference.pdf
+# __IAR_SYSTEMS_ICC__
+# Provides the compiler internal platform version
+# __ICC<arch>__
+# Provides 1 for the current <arch> in use
+# __VER__
+# Provides the current version in use
+# The semantic version of the compiler is architecture-dependent
+# When <arch> is ARM:
+# CMAKE_<LANG>_COMPILER_VERSION_MAJOR = (__VER__ / 1E6)
+# CMAKE_<LANG>_COMPILER_VERSION_MINOR = (__VER__ / 1E3) % 1E3
+# CMAKE_<LANG>_COMPILER_VERSION_PATCH = (__VER__ % 1E3)
+# When <arch> is non-ARM:
+# CMAKE_<LANG>_COMPILER_VERSION_MAJOR = (__VER__ / 1E2)
+# CMAKE_<LANG>_COMPILER_VERSION_MINOR = (__VER__ - ((__VER__/ 1E2) * 1E2))
+# CMAKE_<LANG>_COMPILER_VERSION_PATCH = (__SUBVERSION__)
+# __SUBVERSION__
+# Provides the version's patch level for non-ARM <arch>
#
-# __IAR_SYSTEMS_ICC__ An integer that identifies the IAR compiler platform.
-# __ICCAVR__ An integer that is set to 1 when the code is compiled with the IAR C/C++ Compiler for AVR
-# __VER__ An integer that identifies the version number of the IAR compiler in use.
-# The value is calculated by (100 * VERSION_MAJOR + VERSION_MINOR). For example the version
-# 3.34 is given as 334
-# __SUBVERSION__ An integer that identifies the subversion number of the compiler version number
-# for example 3 in 1.2.3.4. THis is used as the patch version, as seen when running iccavr
-# from the command line
-#
-
set(_compiler_id_pp_test "defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)")
set(_compiler_id_version_compute "
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index 2200a21a7..53456f5c3 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -1,47 +1,15 @@
-# This file is processed when the IAR compiler is used for a C or C++ file
-# Documentation can be downloaded here: http://www.iar.com/website1/1.0.1.0/675/1/
-# The initial feature request is here: https://gitlab.kitware.com/cmake/cmake/-/issues/10176
-# It also contains additional links and information.
-# See USER GUIDES -> C/C++ Development Guide and ReleaseNotes for EWARM:
-# version 6.30.8: http://supp.iar.com/FilesPublic/UPDINFO/006607/arm/doc/infocenter/index.ENU.html
-# version 7.60.1: http://supp.iar.com/FilesPublic/UPDINFO/011006/arm/doc/infocenter/index.ENU.html
-# version 8.10.1: http://netstorage.iar.com/SuppDB/Public/UPDINFO/011854/arm/doc/infocenter/index.ENU.html
-
-# The IAR internal compiler platform generations (Predefined symbol __IAR_SYSTEMS_ICC__):
-# 9 and higher means C11 and C++14 as language default (EWARM v8.x, EWRX v4.x and higher)
-# 8 means C99 and C++03 as language default (EWARM v6.x, v7.x. EWRX v2.x, 3.x)
-# 7 and lower means C89 and EC++ as language default. (EWARM v5.x and lower)
-
-# C/C++ Standard versions
-#
-# IAR typically only supports one C and C++ Standard version,
-# the exception is C89 which is always supported and can be selected
-# if its not the default
-#
-# C++ is trickier, there were historically 3 switches,
-# and some IAR versions support multiple of those.
-# they are --eec++, --ec++ and --c++ and where used to
-# enable various language features like exceptions
-#
-# recent versions only have --c++ for full support
-# but can choose to disable features with further arguments
+# This file is processed when the IAR C/C++ Compiler is used
#
-# C/C++ Standard compliance
+# CPU <arch> supported in CMake: 8051, Arm, AVR, MSP430, RH850, RISC-V, RL78, RX and V850
#
-# IAR has 3 modes: default, strict and extended
-# the extended mode is needed for popular libraries like CMSIS
+# The compiler user documentation is architecture-dependent
+# and it can found with the product installation under <arch>/doc/{EW,BX}<arch>_DevelopmentGuide.ENU.pdf
#
-# "Silent" Operation
#
-# this really is different to most programs I know.
-# nothing meaningful from the operation is lost, just some redundant
-# code and data size printouts (that can be inspected with common tools).
-
-# This module is shared by multiple languages; use include blocker.
include_guard()
macro(__compiler_iar_ilink lang)
- set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".elf")
+ set(CMAKE_EXECUTABLE_SUFFIX ".elf")
set(CMAKE_${lang}_OUTPUT_EXTENSION ".o")
if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX")
set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
@@ -58,14 +26,6 @@ macro(__compiler_iar_ilink lang)
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG")
endif()
- if (${lang} STREQUAL "ASM")
- string(APPEND CMAKE_ASM_FLAGS_INIT " ")
- string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r")
- string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
- string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
- string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
- endif()
-
set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> --silent <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> --create <LINK_FLAGS> <OBJECTS>")
@@ -74,7 +34,7 @@ macro(__compiler_iar_ilink lang)
endmacro()
macro(__compiler_iar_xlink lang)
- set(CMAKE_EXECUTABLE_SUFFIX_${lang} ".bin")
+ set(CMAKE_EXECUTABLE_SUFFIX ".bin")
if (${lang} STREQUAL "C" OR ${lang} STREQUAL "CXX")
set(CMAKE_${lang}_COMPILE_OBJECT "<CMAKE_${lang}_COMPILER> ${CMAKE_IAR_${lang}_FLAG} --silent <SOURCE> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>")
@@ -91,14 +51,6 @@ macro(__compiler_iar_xlink lang)
string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG")
endif()
- if (${lang} STREQUAL "ASM")
- string(APPEND CMAKE_ASM_FLAGS_INIT " ")
- string(APPEND CMAKE_ASM_FLAGS_DEBUG_INIT " -r")
- string(APPEND CMAKE_ASM_FLAGS_MINSIZEREL_INIT " -DNDEBUG")
- string(APPEND CMAKE_ASM_FLAGS_RELEASE_INIT " -DNDEBUG")
- string(APPEND CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT " -r -DNDEBUG")
- endif()
-
set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> -S <OBJECTS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> -o <TARGET>")
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> <TARGET> <LINK_FLAGS> <OBJECTS>")
diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake
index ead9069f3..9884b58c3 100644
--- a/Modules/Compiler/Intel-C.cmake
+++ b/Modules/Compiler/Intel-C.cmake
@@ -17,6 +17,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0)
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11")
diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake
index 37f339a77..7c9cca97e 100644
--- a/Modules/Compiler/Intel-CXX.cmake
+++ b/Modules/Compiler/Intel-CXX.cmake
@@ -16,6 +16,7 @@ endif()
if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0)
set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-Qstd=c++20")
diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake
index d69d06477..d7346f62b 100644
--- a/Modules/Compiler/IntelLLVM-C.cmake
+++ b/Modules/Compiler/IntelLLVM-C.cmake
@@ -4,6 +4,7 @@ __compiler_intel_llvm(C)
if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
AND CMAKE_DEPFILE_FLAGS_C)
diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake
index 979988846..cae1f1199 100644
--- a/Modules/Compiler/IntelLLVM-CXX.cmake
+++ b/Modules/Compiler/IntelLLVM-CXX.cmake
@@ -4,6 +4,7 @@ __compiler_intel_llvm(CXX)
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TP)
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+ set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
AND CMAKE_DEPFILE_FLAGS_CXX)
diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake
index 9a5104bd9..a53df4664 100644
--- a/Modules/Compiler/MSVC-C.cmake
+++ b/Modules/Compiler/MSVC-C.cmake
@@ -11,6 +11,22 @@ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27)
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std:c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std:c11")
+ if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28)
+ set(CMAKE_C90_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_C99_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_C11_STANDARD__HAS_FULL_SUPPORT ON)
+ set(CMAKE_C17_STANDARD_COMPILE_OPTION "-std:c17")
+ set(CMAKE_C17_EXTENSION_COMPILE_OPTION "-std:c17")
+ else()
+ # Special case for 19.27 (VS 16.7): C11 has partial support.
+ macro(cmake_record_c_compile_features)
+ _has_compiler_features_c(90)
+ _has_compiler_features_c(99)
+ list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11)
+ set(_result 0) # expected by cmake_determine_compile_features
+ endmacro()
+ endif()
+
__compiler_check_default_language_standard(C 19.27 99)
else()
# MSVC has no specific options to set C language standards, but set them as
@@ -25,41 +41,42 @@ else()
# There is no meaningful default for this
set(CMAKE_C_STANDARD_DEFAULT "")
+
+ # There are no C compiler modes so we hard-code the known compiler supported
+ # features. Override the default macro for this special case. Pretend that
+ # all language standards are available so that at least compilation
+ # can be attempted.
+ macro(cmake_record_c_compile_features)
+ list(APPEND CMAKE_C_COMPILE_FEATURES
+ c_std_90
+ c_std_99
+ c_std_11
+ c_std_17
+ c_std_23
+ c_function_prototypes
+ )
+ list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes)
+ list(APPEND CMAKE_C99_COMPILE_FEATURES c_std_99)
+ list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11)
+ if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)
+ list(APPEND CMAKE_C_COMPILE_FEATURES c_variadic_macros)
+ list(APPEND CMAKE_C99_COMPILE_FEATURES c_variadic_macros)
+ endif()
+ set(_result 0) # expected by cmake_determine_compile_features
+ endmacro()
endif()
set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC)
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
-
-# There are no C compiler modes so we hard-code the known compiler supported
-# features. Override the default macro for this special case. Pretend that
-# all language standards are available so that at least compilation
-# can be attempted.
-macro(cmake_record_c_compile_features)
- list(APPEND CMAKE_C_COMPILE_FEATURES
- c_std_90
- c_std_99
- c_std_11
- c_function_prototypes
- )
- list(APPEND CMAKE_C90_COMPILE_FEATURES c_std_90 c_function_prototypes)
- list(APPEND CMAKE_C99_COMPILE_FEATURES c_std_99)
- list(APPEND CMAKE_C11_COMPILE_FEATURES c_std_11)
- if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)
- list(APPEND CMAKE_C_COMPILE_FEATURES c_variadic_macros)
- list(APPEND CMAKE_C99_COMPILE_FEATURES c_variadic_macros)
- endif()
- if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.27)
- list(APPEND CMAKE_C_COMPILE_FEATURES c_restrict)
- list(APPEND CMAKE_C99_COMPILE_FEATURES c_restrict)
- endif()
- if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28)
- list(APPEND CMAKE_C_COMPILE_FEATURES c_static_assert)
- list(APPEND CMAKE_C11_COMPILE_FEATURES c_static_assert)
- endif()
- set(_result 0) # expected by cmake_determine_compile_features
-endmacro()
+set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
# /JMC "Just My Code" is only supported by MSVC 19.05 onward.
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
set(CMAKE_C_COMPILE_OPTIONS_JMC "-JMC")
endif()
+
+# The `/external:I` flag was made non-experimental in 19.29.30036.3.
+if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3)
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-external:I ")
+ set(_CMAKE_INCLUDE_SYSTEM_FLAG_C_WARNING "-external:W0 ")
+endif ()
diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake
index 5df5c1ebf..bcaec69e8 100644
--- a/Modules/Compiler/MSVC-CXX.cmake
+++ b/Modules/Compiler/MSVC-CXX.cmake
@@ -4,6 +4,7 @@
include(Compiler/CMakeCommonCompilerMacros)
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
+set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl")
if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR
@@ -80,3 +81,9 @@ endif()
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05)
set(CMAKE_CXX_COMPILE_OPTIONS_JMC "-JMC")
endif()
+
+# The `/external:I` flag was made non-experimental in 19.29.30036.3.
+if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30036.3)
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "-external:I ")
+ set(_CMAKE_INCLUDE_SYSTEM_FLAG_CXX_WARNING "-external:W0 ")
+endif ()
diff --git a/Modules/Compiler/NVHPC.cmake b/Modules/Compiler/NVHPC.cmake
index 70486705c..b51bb4339 100644
--- a/Modules/Compiler/NVHPC.cmake
+++ b/Modules/Compiler/NVHPC.cmake
@@ -12,4 +12,5 @@ include(Compiler/PGI)
macro(__compiler_nvhpc lang)
# Logic specific to NVHPC.
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
endmacro()
diff --git a/Modules/Compiler/PGI.cmake b/Modules/Compiler/PGI.cmake
index 4f8b90b13..d111be9ab 100644
--- a/Modules/Compiler/PGI.cmake
+++ b/Modules/Compiler/PGI.cmake
@@ -26,7 +26,7 @@ macro(__compiler_pgi lang)
endif()
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,")
- set(CMAKE_${lang}_LINKER_WRAPPER_FLAG ",")
+ set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",")
set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le AND (NOT CMAKE_HOST_WIN32 OR CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 16.3))
diff --git a/Modules/CompilerId/VS-10.csproj.in b/Modules/CompilerId/VS-10.csproj.in
index ed5e8476f..fba74ff58 100644
--- a/Modules/CompilerId/VS-10.csproj.in
+++ b/Modules/CompilerId/VS-10.csproj.in
@@ -6,6 +6,9 @@
<Keyword>Win32Proj</Keyword>
@id_system@
@id_system_version@
+ @id_TargetFrameworkVersion@
+ @id_TargetFrameworkIdentifier@
+ @id_TargetFrameworkTargetsVersion@
@id_WindowsTargetPlatformVersion@
@id_WindowsSDKDesktopARMSupport@
</PropertyGroup>
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 9e25beeca..e49faae18 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -224,14 +224,14 @@ External Project Definition
``TLS_CAINFO <file>``
Specify a custom certificate authority file to use if ``TLS_VERIFY``
is enabled. If this option is not specified, the value of the
- ``CMAKE_TLS_CAINFO`` variable will be used instead (see
+ :variable:`CMAKE_TLS_CAINFO` variable will be used instead (see
:command:`file(DOWNLOAD)`)
``NETRC <level>``
.. versionadded:: 3.11
Specify whether the ``.netrc`` file is to be used for operation.
- If this option is not specified, the value of the ``CMAKE_NETRC``
+ If this option is not specified, the value of the :variable:`CMAKE_NETRC`
variable will be used instead (see :command:`file(DOWNLOAD)`)
Valid levels are:
@@ -251,8 +251,8 @@ External Project Definition
Specify an alternative ``.netrc`` file to the one in your home directory
if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
- is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
- be used instead (see :command:`file(DOWNLOAD)`)
+ is not specified, the value of the :variable:`CMAKE_NETRC_FILE` variable
+ will be used instead (see :command:`file(DOWNLOAD)`)
.. versionadded:: 3.1
Added support for `tbz2`, `.tar.xz`, `.txz`, and `.7z` extensions.
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index bd82a90e1..be75689b0 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -21,13 +21,14 @@ supported by the :module:`ExternalProject` module. Whereas
configure step to use the content in commands like :command:`add_subdirectory`,
:command:`include` or :command:`file` operations.
-Content population details would normally be defined separately from the
-command that performs the actual population. This separation ensures that
-all of the dependency details are defined before anything may try to use those
-details to populate content. This is particularly important in more complex
-project hierarchies where dependencies may be shared between multiple projects.
+Content population details should be defined separately from the command that
+performs the actual population. This separation ensures that all the
+dependency details are defined before anything might try to use them to
+populate content. This is particularly important in more complex project
+hierarchies where dependencies may be shared between multiple projects.
-The following shows a typical example of declaring content details:
+The following shows a typical example of declaring content details for some
+dependencies and then ensuring they are populated with a separate call:
.. code-block:: cmake
@@ -36,57 +37,67 @@ The following shows a typical example of declaring content details:
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0
)
+ FetchContent_Declare(
+ myCompanyIcons
+ URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
+ URL_HASH MD5=5588a7b18261c20068beabfb4f530b87
+ )
+
+ FetchContent_MakeAvailable(googletest secret_sauce)
+
+The :command:`FetchContent_MakeAvailable` command ensures the named
+dependencies have been populated, either by an earlier call or by populating
+them itself. When performing the population, it will also add them to the
+main build, if possible, so that the main build can use the populated
+projects' targets, etc. See the command's documentation for how these steps
+are performed.
+
+When using a hierarchical project arrangement, projects at higher levels in
+the hierarchy are able to override the declared details of content specified
+anywhere lower in the project hierarchy. The first details to be declared
+for a given dependency take precedence, regardless of where in the project
+hierarchy that occurs. Similarly, the first call that tries to populate a
+dependency "wins", with subsequent populations reusing the result of the
+first instead of repeating the population again.
+See the :ref:`Examples <fetch-content-examples>` which demonstrate
+this scenario.
-For most typical cases, populating the content can then be done with a single
-command like so:
+In some cases, the main project may need to have more precise control over
+the population, or it may be required to explicitly define the population
+steps in a way that cannot be captured by the declared details alone.
+For such situations, the lower level :command:`FetchContent_GetProperties` and
+:command:`FetchContent_Populate` commands can be used. These lack the richer
+features provided by :command:`FetchContent_MakeAvailable` though, so their
+direct use should be considered a last resort. The typical pattern of such
+custom steps looks like this:
.. code-block:: cmake
- FetchContent_MakeAvailable(googletest)
+ # NOTE: Where possible, prefer to use FetchContent_MakeAvailable()
+ # instead of custom logic like this
-The above command not only populates the content, it also adds it to the main
-build (if possible) so that the main build can use the populated project's
-targets, etc. In some cases, the main project may need to have more precise
-control over the population or may be required to explicitly define the
-population steps (e.g. if CMake versions earlier than 3.14 need to be
-supported). The typical pattern of such custom steps looks like this:
+ # Check if population has already been performed
+ FetchContent_GetProperties(depname)
+ if(NOT depname_POPULATED)
+ # Fetch the content using previously declared details
+ FetchContent_Populate(depname)
-.. code-block:: cmake
+ # Set custom variables, policies, etc.
+ # ...
- FetchContent_GetProperties(googletest)
- if(NOT googletest_POPULATED)
- FetchContent_Populate(googletest)
- add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
+ # Bring the populated content into the build
+ add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR})
endif()
-Regardless of which population method is used, when using the
-declare-populate pattern with a hierarchical project arrangement, projects at
-higher levels in the hierarchy are able to override the population details of
-content specified anywhere lower in the project hierarchy. The ability to
-detect whether content has already been populated ensures that even if
-multiple child projects want certain content to be available, the first one
-to populate it wins. The other child project can simply make use of the
-already available content instead of repeating the population for itself.
-See the :ref:`Examples <fetch-content-examples>` section which demonstrates
-this scenario.
-
The ``FetchContent`` module also supports defining and populating
content in a single call, with no check for whether the content has been
-populated elsewhere in the project already. This is a more low level
-operation and would not normally be the way the module is used, but it is
-sometimes useful as part of implementing some higher level feature or to
-populate some content in CMake's script mode.
-
-.. versionchanged:: 3.14
- ``FetchContent`` commands can access the terminal. This is necessary
- for password prompts and real-time progress displays to work.
+populated elsewhere already. This should not be done in projects, but may
+be appropriate for populating content in CMake's script mode.
+See :command:`FetchContent_Populate` for details.
Commands
^^^^^^^^
-Declaring Content Details
-"""""""""""""""""""""""""
-
.. command:: FetchContent_Declare
.. code-block:: cmake
@@ -94,7 +105,7 @@ Declaring Content Details
FetchContent_Declare(<name> <contentOptions>...)
The ``FetchContent_Declare()`` function records the options that describe
- how to populate the specified content, but if such details have already
+ how to populate the specified content. If such details have already
been recorded earlier in this project (regardless of where in the project
hierarchy), this and all later calls for the same content ``<name>`` are
ignored. This "first to record, wins" approach is what allows hierarchical
@@ -110,7 +121,7 @@ Declaring Content Details
projects needing that same content will use the same name, leading to
the content being populated multiple times.
- The ``<contentOptions>`` can be any of the download or update/patch options
+ The ``<contentOptions>`` can be any of the download, update or patch options
that the :command:`ExternalProject_Add` command understands. The configure,
build, install and test steps are explicitly disabled and therefore options
related to them will be ignored. The ``SOURCE_SUBDIR`` option is an
@@ -146,47 +157,95 @@ Declaring Content Details
than a branch or tag name. A commit hash is more secure and helps to
confirm that the downloaded contents are what you expected.
-Populating The Content
-""""""""""""""""""""""
+ .. versionchanged:: 3.14
+ Commands for the download, update or patch steps can access the terminal.
+ This may be needed for things like password prompts or real-time display
+ of command progress.
-For most common scenarios, population means making content available to the
-main build according to previously declared details for that dependency.
-There are two main patterns for populating content, one based on calling
-:command:`FetchContent_GetProperties` and
-:command:`FetchContent_Populate` for more precise control and the other on
-calling :command:`FetchContent_MakeAvailable` for a simpler, more automated
-approach. The former generally follows this canonical pattern:
+ .. versionadded:: 3.22
+ The :variable:`CMAKE_TLS_VERIFY`, :variable:`CMAKE_TLS_CAINFO`,
+ :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables now
+ provide the defaults for their corresponding content options, just like
+ they do for :command:`ExternalProject_Add`. Previously, these variables
+ were ignored by the ``FetchContent`` module.
-.. _`fetch-content-canonical-pattern`:
+.. command:: FetchContent_MakeAvailable
-.. code-block:: cmake
+ .. versionadded:: 3.14
- # Check if population has already been performed
- FetchContent_GetProperties(<name>)
- string(TOLOWER "<name>" lcName)
- if(NOT ${lcName}_POPULATED)
- # Fetch the content using previously declared details
- FetchContent_Populate(<name>)
+ .. code-block:: cmake
- # Set custom variables, policies, etc.
- # ...
+ FetchContent_MakeAvailable(<name1> [<name2>...])
+
+ This command ensures that each of the named dependencies are populated and
+ potentially added to the build by the time it returns. It iterates over
+ the list, and for each dependency, the following logic is applied:
+
+ * If the dependency has already been populated earlier in this run, set
+ the ``<lowercaseName>_POPULATED``, ``<lowercaseName>_SOURCE_DIR`` and
+ ``<lowercaseName>_BINARY_DIR`` variables in the same way as a call to
+ :command:`FetchContent_GetProperties`, then skip the remaining steps
+ below and move on to the next dependency in the list.
+
+ * Call :command:`FetchContent_Populate` to populate the dependency using
+ the details recorded by an earlier call to :command:`FetchContent_Declare`.
+ Halt with a fatal error if no such details have been recorded.
+ :variable:`FETCHCONTENT_SOURCE_DIR_<uppercaseName>` can be used to override
+ the declared details and use content provided at the specified location
+ instead.
+
+ * If the top directory of the populated content contains a ``CMakeLists.txt``
+ file, call :command:`add_subdirectory` to add it to the main build.
+ It is not an error for there to be no ``CMakeLists.txt`` file, which
+ allows the command to be used for dependencies that make downloaded
+ content available at a known location, but which do not need or support
+ being added directly to the build.
+
+ .. versionadded:: 3.18
+ The ``SOURCE_SUBDIR`` option can be given in the declared details to
+ look somewhere below the top directory instead (i.e. the same way that
+ ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add`
+ command). The path provided with ``SOURCE_SUBDIR`` must be relative
+ and will be treated as relative to the top directory. It can also
+ point to a directory that does not contain a ``CMakeLists.txt`` file
+ or even to a directory that doesn't exist. This can be used to avoid
+ adding a project that contains a ``CMakeLists.txt`` file in its top
+ directory.
+
+ Projects should aim to declare the details of all dependencies they might
+ use before they call ``FetchContent_MakeAvailable()`` for any of them.
+ This ensures that if any of the dependencies are also sub-dependencies of
+ one or more of the others, the main project still controls the details
+ that will be used (because it will declare them first before the
+ dependencies get a chance to). In the following code samples, assume that
+ the ``uses_other`` dependency also uses ``FetchContent`` to add the ``other``
+ dependency internally:
- # Bring the populated content into the build
- add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR})
- endif()
+ .. code-block:: cmake
+
+ # WRONG: Should declare all details first
+ FetchContent_Declare(uses_other ...)
+ FetchContent_MakeAvailable(uses_other)
-The above is such a common pattern that, where no custom steps are needed
-between the calls to :command:`FetchContent_Populate` and
-:command:`add_subdirectory`, equivalent logic can be obtained by calling
-:command:`FetchContent_MakeAvailable` instead. Where it meets the needs of
-the project, :command:`FetchContent_MakeAvailable` should be preferred, as it
-is simpler and provides additional features over the pattern above.
+ FetchContent_Declare(other ...) # Will be ignored, uses_other beat us to it
+ FetchContent_MakeAvailable(other) # Would use details declared by uses_other
+
+ .. code-block:: cmake
+
+ # CORRECT: All details declared first, so they will take priority
+ FetchContent_Declare(uses_other ...)
+ FetchContent_Declare(other ...)
+ FetchContent_MakeAvailable(uses_other other)
.. command:: FetchContent_Populate
+ .. note::
+ Where possible, prefer to use :command:`FetchContent_MakeAvailable`
+ instead of implementing population manually with this command.
+
.. code-block:: cmake
- FetchContent_Populate( <name> )
+ FetchContent_Populate(<name>)
In most cases, the only argument given to ``FetchContent_Populate()`` is the
``<name>``. When used this way, the command assumes the content details have
@@ -211,88 +270,29 @@ is simpler and provides additional features over the pattern above.
``FetchContent_Populate()``.
``FetchContent_Populate()`` will set three variables in the scope of the
- caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and
- ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``.
- ``<lcName>_POPULATED`` will always be set to ``True`` by the call.
- ``<lcName>_SOURCE_DIR`` is the location where the
- content can be found upon return (it will have already been populated), while
- ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding
- build directory. The main use case for the two directory variables is to
- call :command:`add_subdirectory` immediately after population, i.e.:
+ caller:
+
+ ``<lowercaseName>_POPULATED``
+ This will always be set to ``TRUE`` by the call.
+
+ ``<lowercaseName>_SOURCE_DIR``
+ The location where the populated content can be found upon return.
+
+ ``<lowercaseName>_BINARY_DIR``
+ A directory intended for use as a corresponding build directory.
+
+ The main use case for the ``<lowercaseName>_SOURCE_DIR`` and
+ ``<lowercaseName>_BINARY_DIR`` variables is to call
+ :command:`add_subdirectory` immediately after population:
.. code-block:: cmake
- FetchContent_Populate(FooBar ...)
+ FetchContent_Populate(FooBar)
add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})
The values of the three variables can also be retrieved from anywhere in the
project hierarchy using the :command:`FetchContent_GetProperties` command.
- A number of cache variables influence the behavior of all content population
- performed using details saved from a :command:`FetchContent_Declare` call:
-
- ``FETCHCONTENT_BASE_DIR``
- In most cases, the saved details do not specify any options relating to the
- directories to use for the internal sub-build, final source and build areas.
- It is generally best to leave these decisions up to the ``FetchContent``
- module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR``
- cache variable controls the point under which all content population
- directories are collected, but in most cases developers would not need to
- change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if
- developers change this value, they should aim to keep the path short and
- just below the top level of the build tree to avoid running into path
- length problems on Windows.
-
- ``FETCHCONTENT_QUIET``
- The logging output during population can be quite verbose, making the
- configure stage quite noisy. This cache option (``ON`` by default) hides
- all population output unless an error is encountered. If experiencing
- problems with hung downloads, temporarily switching this option off may
- help diagnose which content population is causing the issue.
-
- ``FETCHCONTENT_FULLY_DISCONNECTED``
- When this option is enabled, no attempt is made to download or update
- any content. It is assumed that all content has already been populated in
- a previous run or the source directories have been pointed at existing
- contents the developer has provided manually (using options described
- further below). When the developer knows that no changes have been made to
- any content details, turning this option ``ON`` can significantly speed up
- the configure stage. It is ``OFF`` by default.
-
- ``FETCHCONTENT_UPDATES_DISCONNECTED``
- This is a less severe download/update control compared to
- ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and
- update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the
- update stage. Therefore, if content has not been downloaded previously,
- it will still be downloaded when this option is enabled. This can speed up
- the configure stage, but not as much as
- ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default.
-
- In addition to the above cache variables, the following cache variables are
- also defined for each content name (``<ucName>`` is the uppercased value of
- ``<name>``):
-
- ``FETCHCONTENT_SOURCE_DIR_<ucName>``
- If this is set, no download or update steps are performed for the specified
- content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is
- pointed at this location. This gives developers a way to have a separate
- checkout of the content that they can modify freely without interference
- from the build. The build simply uses that existing source, but it still
- defines ``<lcName>_BINARY_DIR`` to point inside its own build area.
- Developers are strongly encouraged to use this mechanism rather than
- editing the sources populated in the default location, as changes to
- sources in the default location can be lost when content population details
- are changed by the project.
-
- ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>``
- This is the per-content equivalent of
- ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option
- is ``ON``, then updates will be disabled for the named content.
- Disabling updates for individual content can be useful for content whose
- details rarely change, while still leaving other frequently changing
- content with updates enabled.
-
-
The ``FetchContent_Populate()`` command also supports a syntax allowing the
content details to be specified directly rather than using any saved
details. This is more low-level and use of this form is generally to be
@@ -303,7 +303,8 @@ is simpler and provides additional features over the pattern above.
.. code-block:: cmake
- FetchContent_Populate( <name>
+ FetchContent_Populate(
+ <name>
[QUIET]
[SUBBUILD_DIR <subBuildDir>]
[SOURCE_DIR <srcDir>]
@@ -325,16 +326,17 @@ is simpler and provides additional features over the pattern above.
- The ``FETCHCONTENT_FULLY_DISCONNECTED`` and
``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored.
- The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still
- returned to the caller, but since these locations are not stored as global
- properties when this form is used, they are only available to the calling
- scope and below rather than the entire project hierarchy. No
- ``<lcName>_POPULATED`` variable is set in the caller's scope with this form.
+ The ``<lowercaseName>_SOURCE_DIR`` and ``<lowercaseName>_BINARY_DIR``
+ variables are still returned to the caller, but since these locations are
+ not stored as global properties when this form is used, they are only
+ available to the calling scope and below rather than the entire project
+ hierarchy. No ``<lowercaseName>_POPULATED`` variable is set in the caller's
+ scope with this form.
The supported options for ``FetchContent_Populate()`` are the same as those
for :command:`FetchContent_Declare()`. Those few options shown just
above are either specific to ``FetchContent_Populate()`` or their behavior is
- slightly modified from how :command:`ExternalProject_Add` treats them.
+ slightly modified from how :command:`ExternalProject_Add` treats them:
``QUIET``
The ``QUIET`` option can be given to hide the output associated with
@@ -347,9 +349,9 @@ is simpler and provides additional features over the pattern above.
``SUBBUILD_DIR``
The ``SUBBUILD_DIR`` argument can be provided to change the location of the
sub-build created to perform the population. The default value is
- ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual
- to need to override this default. If a relative path is specified, it will
- be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-subbuild`` and it would be
+ unusual to need to override this default. If a relative path is specified,
+ it will be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
This option should not be confused with the ``SOURCE_SUBDIR`` option which
only affects the :command:`FetchContent_MakeAvailable` command.
@@ -357,9 +359,9 @@ is simpler and provides additional features over the pattern above.
The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by
:command:`ExternalProject_Add`, but different default values are used by
``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to
- ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to
- ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``. If a relative path is
- specified, it will be interpreted as relative to
+ ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-src`` and ``BINARY_DIR``
+ defaults to ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-build``.
+ If a relative path is specified, it will be interpreted as relative to
:variable:`CMAKE_CURRENT_BINARY_DIR`.
In addition to the above explicit options, any other unrecognized options are
@@ -380,11 +382,12 @@ is simpler and provides additional features over the pattern above.
on the command line invoking the script.
.. versionadded:: 3.18
- Added support for ``DOWNLOAD_NO_EXTRACT`` and ``SOURCE_SUBDIR`` options.
+ Added support for the ``DOWNLOAD_NO_EXTRACT`` option.
.. command:: FetchContent_GetProperties
- When using saved content details, a call to :command:`FetchContent_Populate`
+ When using saved content details, a call to
+ :command:`FetchContent_MakeAvailable` or :command:`FetchContent_Populate`
records information in global properties which can be queried at any time.
This information includes the source and binary directories associated with
the content and also whether or not the content population has been processed
@@ -392,7 +395,8 @@ is simpler and provides additional features over the pattern above.
.. code-block:: cmake
- FetchContent_GetProperties( <name>
+ FetchContent_GetProperties(
+ <name>
[SOURCE_DIR <srcDirVar>]
[BINARY_DIR <binDirVar>]
[POPULATED <doneVar>]
@@ -403,49 +407,104 @@ is simpler and provides additional features over the pattern above.
which is the name of the variable in which to store that property. Most of
the time though, only ``<name>`` is given, in which case the call will then
set the same variables as a call to
- :command:`FetchContent_Populate(name) <FetchContent_Populate>`. This allows
- the following canonical pattern to be used, which ensures that the relevant
- variables will always be defined regardless of whether or not the population
- has been performed elsewhere in the project already:
+ :command:`FetchContent_MakeAvailable(name) <FetchContent_MakeAvailable>` or
+ :command:`FetchContent_Populate(name) <FetchContent_Populate>`.
- .. code-block:: cmake
-
- FetchContent_GetProperties(foobar)
- if(NOT foobar_POPULATED)
- FetchContent_Populate(foobar)
- ...
- endif()
-
- The above pattern allows other parts of the overall project hierarchy to
- re-use the same content and ensure that it is only populated once.
-
-
-.. command:: FetchContent_MakeAvailable
+ This command is rarely needed when using
+ :command:`FetchContent_MakeAvailable`. It is more commonly used as part of
+ implementing the following pattern with :command:`FetchContent_Populate`,
+ which ensures that the relevant variables will always be defined regardless
+ of whether or not the population has been performed elsewhere in the project
+ already:
.. code-block:: cmake
- FetchContent_MakeAvailable( <name1> [<name2>...] )
+ # Check if population has already been performed
+ FetchContent_GetProperties(depname)
+ if(NOT depname_POPULATED)
+ # Fetch the content using previously declared details
+ FetchContent_Populate(depname)
- .. versionadded:: 3.14
+ # Set custom variables, policies, etc.
+ # ...
- This command implements the common pattern typically needed for most
- dependencies. It iterates over each of the named dependencies in turn
- and for each one it loosely follows the
- :ref:`canonical pattern <fetch-content-canonical-pattern>` as
- presented at the beginning of this section. An important difference is
- that :command:`add_subdirectory` will only be called on the
- populated content if there is a ``CMakeLists.txt`` file in its top level
- source directory. This allows the command to be used for dependencies
- that make downloaded content available at a known location but which do
- not need or support being added directly to the build.
-
- The ``SOURCE_SUBDIR`` option can be given in the declared details to
- instruct ``FetchContent_MakeAvailable()`` to look for a ``CMakeLists.txt``
- file in a subdirectory below the top level (i.e. the same way that
- ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` command).
- ``SOURCE_SUBDIR`` must always be a relative path. See the next section
- for an example of this option.
+ # Bring the populated content into the build
+ add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR})
+ endif()
+Variables
+^^^^^^^^^
+
+A number of cache variables can influence the behavior where details from a
+:command:`FetchContent_Declare` call are used to populate content.
+The variables are all intended for the developer to customize behavior and
+should not normally be set by the project.
+
+.. variable:: FETCHCONTENT_BASE_DIR
+
+ In most cases, the saved details do not specify any options relating to the
+ directories to use for the internal sub-build, final source and build areas.
+ It is generally best to leave these decisions up to the ``FetchContent``
+ module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR``
+ cache variable controls the point under which all content population
+ directories are collected, but in most cases, developers would not need to
+ change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if
+ developers change this value, they should aim to keep the path short and
+ just below the top level of the build tree to avoid running into path
+ length problems on Windows.
+
+.. variable:: FETCHCONTENT_QUIET
+
+ The logging output during population can be quite verbose, making the
+ configure stage quite noisy. This cache option (``ON`` by default) hides
+ all population output unless an error is encountered. If experiencing
+ problems with hung downloads, temporarily switching this option off may
+ help diagnose which content population is causing the issue.
+
+.. variable:: FETCHCONTENT_FULLY_DISCONNECTED
+
+ When this option is enabled, no attempt is made to download or update
+ any content. It is assumed that all content has already been populated in
+ a previous run or the source directories have been pointed at existing
+ contents the developer has provided manually (using options described
+ further below). When the developer knows that no changes have been made to
+ any content details, turning this option ``ON`` can significantly speed up
+ the configure stage. It is ``OFF`` by default.
+
+.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED
+
+ This is a less severe download/update control compared to
+ :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. Instead of bypassing all
+ download and update logic, ``FETCHCONTENT_UPDATES_DISCONNECTED`` only
+ disables the update stage. Therefore, if content has not been downloaded
+ previously, it will still be downloaded when this option is enabled.
+ This can speed up the configure stage, but not as much as
+ :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default.
+
+In addition to the above cache variables, the following cache variables are
+also defined for each content name:
+
+.. variable:: FETCHCONTENT_SOURCE_DIR_<uppercaseName>
+
+ If this is set, no download or update steps are performed for the specified
+ content and the ``<lowercaseName>_SOURCE_DIR`` variable returned to the
+ caller is pointed at this location. This gives developers a way to have a
+ separate checkout of the content that they can modify freely without
+ interference from the build. The build simply uses that existing source,
+ but it still defines ``<lowercaseName>_BINARY_DIR`` to point inside its own
+ build area. Developers are strongly encouraged to use this mechanism rather
+ than editing the sources populated in the default location, as changes to
+ sources in the default location can be lost when content population details
+ are changed by the project.
+
+.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName>
+
+ This is the per-content equivalent of
+ :variable:`FETCHCONTENT_UPDATES_DISCONNECTED`. If the global option or
+ this option is ``ON``, then updates will be disabled for the named content.
+ Disabling updates for individual content can be useful for content whose
+ details rarely change, while still leaving other frequently changing content
+ with updates enabled.
.. _`fetch-content-examples`:
@@ -470,7 +529,7 @@ frameworks are available to the main build:
)
# After the following call, the CMake targets defined by googletest and
- # Catch2 will be defined and available to the rest of the build
+ # Catch2 will be available to the rest of the build
FetchContent_MakeAvailable(googletest Catch2)
If the sub-project's ``CMakeLists.txt`` file is not at the top level of its
@@ -964,18 +1023,29 @@ ExternalProject_Add_Step(${contentName}-populate copyfile
unset(subCMakeOpts)
endif()
- if(DEFINED CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY)
- list(APPEND subCMakeOpts
- "-DCMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY=${CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY}")
- endif()
+ set(__FETCHCONTENT_CACHED_INFO "")
+ set(__passthrough_vars
+ CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY
+ CMAKE_TLS_VERIFY
+ CMAKE_TLS_CAINFO
+ CMAKE_NETRC
+ CMAKE_NETRC_FILE
+ )
+ foreach(var IN LISTS __passthrough_vars)
+ if(DEFINED ${var})
+ # Embed directly in the generated CMakeLists.txt file to avoid making
+ # the cmake command line excessively long. It also makes debugging and
+ # testing easier.
+ string(APPEND __FETCHCONTENT_CACHED_INFO "set(${var} [==[${${var}}]==])\n")
+ endif()
+ endforeach()
# Avoid using if(... IN_LIST ...) so we don't have to alter policy settings
- set(__FETCHCONTENT_CACHED_INFO "")
list(FIND ARG_UNPARSED_ARGUMENTS GIT_REPOSITORY indexResult)
if(indexResult GREATER_EQUAL 0)
find_package(Git QUIET)
- set(__FETCHCONTENT_CACHED_INFO
-"# Pass through things we've already detected in the main project to avoid
+ string(APPEND __FETCHCONTENT_CACHED_INFO "
+# Pass through things we've already detected in the main project to avoid
# paying the cost of redetecting them again in ExternalProject_Add()
set(GIT_EXECUTABLE [==[${GIT_EXECUTABLE}]==])
set(GIT_VERSION_STRING [==[${GIT_VERSION_STRING}]==])
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 726ff75bf..308138f41 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -35,6 +35,19 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a BLAS library first
and if one is found that is preferred
+``BLA_SIZEOF_INTEGER``
+ .. versionadded:: 3.22
+
+ Specify the BLAS/LAPACK library integer size:
+
+ ``4``
+ Search for a BLAS/LAPACK with 32-bit integer interfaces.
+ ``8``
+ Search for a BLAS/LAPACK with 64-bit integer interfaces.
+ ``ANY``
+ Search for any BLAS/LAPACK.
+ Most likely, a BLAS/LAPACK with 32-bit integer interfaces will be found.
+
Imported targets
^^^^^^^^^^^^^^^^
@@ -101,15 +114,16 @@ BLAS/LAPACK Vendors
``FlexiBLAS``
.. versionadded:: 3.19
-``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``
+``Fujitsu_SSL2``, ``Fujitsu_SSL2BLAMP``, ``Fujitsu_SSL2SVE``, ``Fujitsu_SSL2BLAMPSVE``
.. versionadded:: 3.20
- Fujitsu SSL2 serial and parallel blas/lapack
+ Fujitsu SSL2 serial and parallel blas/lapack with SVE instructions
``Goto``
GotoBLAS
-``IBMESSL``
+``IBMESSL``, ``IBMESSL_SMP``
+
IBM Engineering and Scientific Subroutine Library
``Intel``
@@ -150,7 +164,7 @@ BLAS/LAPACK Vendors
``PhiPACK``
Portable High Performance ANSI C (PHiPAC)
-``SCSL``
+``SCSL``, ``SCSL_mp``
Scientific Computing Software Library
``SGIMATH``
@@ -312,9 +326,9 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib
list(APPEND _libraries "${_library}")
else()
string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}")
- set(_combined_name ${_combined_name}_${_lib_var})
+ string(APPEND _combined_name "_${_lib_var}")
if(NOT "${_deps}" STREQUAL "")
- set(_combined_name ${_combined_name}_deps)
+ string(APPEND _combined_name "_deps")
endif()
if(_libraries_work)
find_library(${_prefix}_${_lib_var}_LIBRARY
@@ -332,7 +346,7 @@ function(CHECK_BLAS_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addlib
foreach(_flag ${_flags})
string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}")
- set(_combined_name ${_combined_name}_${_flag_var})
+ string(APPEND _combined_name "_${_flag_var}")
endforeach()
if(_libraries_work)
# Test this combination of libraries.
@@ -371,6 +385,17 @@ else()
endif()
endif()
+if(NOT BLA_SIZEOF_INTEGER)
+ # in the reality we do not know which API of BLAS/LAPACK is masked in library
+ set(_blas_sizeof_integer "ANY")
+elseif((BLA_SIZEOF_INTEGER STREQUAL "ANY") OR
+ (BLA_SIZEOF_INTEGER STREQUAL "4") OR
+ (BLA_SIZEOF_INTEGER STREQUAL "8"))
+ set(_blas_sizeof_integer ${BLA_SIZEOF_INTEGER})
+else()
+ message(FATAL_ERROR "BLA_SIZEOF_INTEGER can have only <no value>, ANY, 4, or 8 values")
+endif()
+
# Implicitly linked BLAS libraries?
if(BLA_VENDOR STREQUAL "All")
if(NOT BLAS_LIBRARIES)
@@ -386,6 +411,8 @@ if(BLA_VENDOR STREQUAL "All")
)
endif()
if(BLAS_WORKS)
+ # Give a more helpful "found" message
+ set(BLAS_WORKS "implicitly linked")
set(_blas_fphsa_req_var BLAS_WORKS)
endif()
endif()
@@ -429,17 +456,23 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
find_package(Threads REQUIRED)
endif()
- if(BLA_VENDOR MATCHES "_64ilp")
+ if(_blas_sizeof_integer EQUAL 8)
set(BLAS_mkl_ILP_MODE "ilp64")
- else()
+ elseif(_blas_sizeof_integer EQUAL 4)
set(BLAS_mkl_ILP_MODE "lp64")
+ else()
+ if(BLA_VENDOR MATCHES "_64ilp")
+ set(BLAS_mkl_ILP_MODE "ilp64")
+ else()
+ set(BLAS_mkl_ILP_MODE "lp64")
+ endif()
endif()
set(BLAS_SEARCH_LIBS "")
if(BLA_F95)
set(BLAS_mkl_SEARCH_SYMBOL "sgemm_f95")
- set(_LIBRARIES BLAS95_LIBRARIES)
+ set(_BLAS_LIBRARIES BLAS95_LIBRARIES)
if(WIN32)
# Find the main file (32-bit or 64-bit)
set(BLAS_SEARCH_LIBS_WIN_MAIN "")
@@ -501,7 +534,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
endif()
else()
set(BLAS_mkl_SEARCH_SYMBOL sgemm)
- set(_LIBRARIES BLAS_LIBRARIES)
+ set(_BLAS_LIBRARIES BLAS_LIBRARIES)
if(WIN32)
# Find the main file (32-bit or 64-bit)
set(BLAS_SEARCH_LIBS_WIN_MAIN "")
@@ -613,15 +646,15 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
"lib/${BLAS_mkl_ARCH_NAME}"
)
- foreach(IT ${BLAS_SEARCH_LIBS})
- string(REPLACE " " ";" SEARCH_LIBS ${IT})
- if(NOT ${_LIBRARIES})
+ foreach(_search ${BLAS_SEARCH_LIBS})
+ string(REPLACE " " ";" _search ${_search})
+ if(NOT ${_BLAS_LIBRARIES})
check_blas_libraries(
- ${_LIBRARIES}
+ ${_BLAS_LIBRARIES}
BLAS
${BLAS_mkl_SEARCH_SYMBOL}
""
- "${SEARCH_LIBS}"
+ "${_search}"
"${CMAKE_THREAD_LIBS_INIT};${BLAS_mkl_LM};${BLAS_mkl_LDL}"
"${BLAS_mkl_MKLROOT}"
"${BLAS_mkl_LIB_PATH_SUFFIXES}"
@@ -629,6 +662,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
endif()
endforeach()
+ unset(_search)
unset(BLAS_mkl_ILP_MODE)
unset(BLAS_mkl_INTFACE)
unset(BLAS_mkl_THREADING)
@@ -671,29 +705,43 @@ endif()
# FlexiBLAS? (http://www.mpi-magdeburg.mpg.de/mpcsc/software/FlexiBLAS/)
if(BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_flexiblas_lib "flexiblas")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_flexiblas_lib "64")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "flexiblas"
+ "${_blas_flexiblas_lib}"
""
""
""
)
endif()
+
+ unset(_blas_flexiblas_lib)
endif()
# OpenBLAS? (http://www.openblas.net)
if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_openblas_lib "openblas")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_openblas_lib "64")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "openblas"
+ "${_blas_openblas_lib}"
""
""
""
@@ -720,59 +768,75 @@ if(BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All")
BLAS
sgemm
""
- "openblas"
+ "${_blas_openblas_lib}"
"${_threadlibs}"
""
""
)
unset(_threadlibs)
endif()
+
+ unset(_blas_openblas_lib)
endif()
# ArmPL blas library? (https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux/arm-performance-libraries)
if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All")
# Check for 64bit Integer support
- if(BLA_VENDOR MATCHES "_ilp64")
- set(BLAS_armpl_LIB "armpl_ilp64")
- else()
- set(BLAS_armpl_LIB "armpl_lp64")
- endif()
+ if(_blas_sizeof_integer EQUAL 8)
+ set(_blas_armpl_lib "armpl_ilp64")
+ elseif(_blas_sizeof_integer EQUAL 4)
+ set(_blas_armpl_lib "armpl_lp64")
+ else()
+ if(BLA_VENDOR MATCHES "_ilp64")
+ set(_blas_armpl_lib "armpl_ilp64")
+ else()
+ set(_blas_armpl_lib "armpl_lp64")
+ endif()
+ endif()
# Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp
if(BLA_VENDOR MATCHES "_mp")
- set(BLAS_armpl_LIB "${BLAS_armpl_LIB}_mp")
+ string(APPEND _blas_armpl_lib "_mp")
endif()
if(NOT BLAS_LIBRARIES)
- check_blas_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "${BLAS_armpl_LIB}"
- ""
- ""
- ""
- )
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "${_blas_armpl_lib}"
+ ""
+ ""
+ ""
+ )
endif()
-
+ unset(_blas_armpl_lib)
endif()
# FLAME's blis library? (https://github.com/flame/blis)
if(BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_flame_lib "blis")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_flame_lib "64")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "blis"
+ "${_blas_flame_lib}"
""
""
""
)
endif()
+
+ unset(_blas_flame_lib)
endif()
# BLAS in the ATLAS library? (http://math-atlas.sourceforge.net/)
@@ -809,33 +873,45 @@ endif()
# BLAS in Alpha CXML library?
if(BLA_VENDOR STREQUAL "CXML" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_blas_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "cxml"
- ""
- ""
- ""
- )
+ if(_blas_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "CXML")
+ message(FATAL_ERROR "CXML does not support Int64 type")
+ endif()
+ else()
+ if(NOT BLAS_LIBRARIES)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "cxml"
+ ""
+ ""
+ ""
+ )
+ endif()
endif()
endif()
# BLAS in Alpha DXML library? (now called CXML, see above)
if(BLA_VENDOR STREQUAL "DXML" OR BLA_VENDOR STREQUAL "All")
- if(NOT BLAS_LIBRARIES)
- check_blas_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- ""
- "dxml"
- ""
- ""
- ""
- )
+ if(_blas_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "DXML")
+ message(FATAL_ERROR "DXML does not support Int64 type")
+ endif()
+ else()
+ if(NOT BLAS_LIBRARIES)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "dxml"
+ ""
+ ""
+ ""
+ )
+ endif()
endif()
endif()
@@ -859,19 +935,30 @@ if(BLA_VENDOR STREQUAL "SunPerf" OR BLA_VENDOR STREQUAL "All")
endif()
# BLAS in SCSL library? (SGI/Cray Scientific Library)
-if(BLA_VENDOR STREQUAL "SCSL" OR BLA_VENDOR STREQUAL "All")
+if(BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_scsl_lib "scs")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_scsl_lib "_i8")
+ endif()
+ if(BLA_VENDOR MATCHES "_mp")
+ string(APPEND _blas_scsl_lib "_mp")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "scsl"
+ "${_blas_scsl_lib}"
""
""
""
)
endif()
+
+ unset(_blas_scsl_lib)
endif()
# BLAS in SGIMATH library?
@@ -890,20 +977,31 @@ if(BLA_VENDOR STREQUAL "SGIMATH" OR BLA_VENDOR STREQUAL "All")
endif()
endif()
-# BLAS in IBM ESSL library? (requires generic BLAS lib, too)
-if(BLA_VENDOR STREQUAL "IBMESSL" OR BLA_VENDOR STREQUAL "All")
+# BLAS in IBM ESSL library?
+if(BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_essl_lib "essl")
+
+ if(BLA_VENDOR MATCHES "_SMP")
+ string(APPEND _blas_essl_lib "smp")
+ endif()
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_essl_lib "6464")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "essl;blas"
+ "${_blas_essl_lib}"
""
""
""
)
endif()
+
+ unset(_blas_essl_lib)
endif()
# BLAS in acml library?
@@ -927,7 +1025,7 @@ if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
list(GET _ACML_GPU_ROOT 0 _ACML_GPU_ROOT)
if(_ACML_ROOT)
get_filename_component(_ACML_ROOT ${_ACML_ROOT} PATH)
- if(SIZEOF_INTEGER EQUAL 8)
+ if(_blas_sizeof_integer EQUAL 8)
set(_ACML_PATH_SUFFIX "_int64")
else()
set(_ACML_PATH_SUFFIX "")
@@ -1054,102 +1152,179 @@ endif() # ACML
# Apple BLAS library?
if(BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All")
+ if(_blas_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "Apple")
+ message(FATAL_ERROR "Accelerate Framework does not support Int64 type")
+ endif()
+ else()
+ if(NOT BLAS_LIBRARIES)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ dgemm
+ ""
+ "Accelerate"
+ ""
+ ""
+ ""
+ )
+ endif()
+ endif()
+endif()
+
+# Apple NAS (vecLib) library?
+if(BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All")
+ if(_blas_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "NAS")
+ message(FATAL_ERROR "Accelerate Framework does not support Int64 type")
+ endif()
+ else()
+ if(NOT BLAS_LIBRARIES)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ dgemm
+ ""
+ "vecLib"
+ ""
+ ""
+ ""
+ )
+ endif()
+ endif()
+endif()
+
+# Elbrus Math Library?
+if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
+
+ set(_blas_eml_lib "eml")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_eml_lib "_ilp64")
+ endif()
+ # Check for OpenMP support, VIA BLA_VENDOR of eml_mt
+ if(BLA_VENDOR MATCHES "_mt")
+ string(APPEND _blas_eml_lib "_mt")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
- dgemm
+ sgemm
""
- "Accelerate"
+ "${_blas_eml_lib}"
""
""
""
)
endif()
+ unset(_blas_eml_lib)
endif()
-# Apple NAS (vecLib) library?
-if(BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All")
+# Fujitsu SSL2 Library?
+if(NOT BLAS_LIBRARIES
+ AND (BLA_VENDOR MATCHES "^Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All"))
+ set(_blas_fjlapack_lib "fjlapack")
+ set(_blas_fjlapack_flags "-Kopenmp")
+
+ if(BLA_VENDOR MATCHES "BLAMP")
+ string(APPEND _blas_fjlapack_lib "ex")
+ endif()
+ if(BLA_VENDOR MATCHES "SVE")
+ string(APPEND _blas_fjlapack_lib "sve")
+ endif()
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_fjlapack_lib "_ilp64")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
- dgemm
- ""
- "vecLib"
+ sgemm
+ "${_blas_fjlapack_flags}"
+ "${_blas_fjlapack_lib}"
""
""
""
)
+ if(BLAS_LIBRARIES)
+ set(BLAS_LINKER_FLAGS ${_blas_fjlapack_flags})
+ endif()
endif()
-endif()
-# Elbrus Math Library?
-if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
+ unset(_blas_fjlapack_flags)
+ unset(_blas_fjlapack_lib)
+endif()
- set(BLAS_EML_LIB "eml")
+# BLAS in nVidia HPC SDK? (https://developer.nvidia.com/hpc-sdk)
+if(BLA_VENDOR STREQUAL "NVHPC" OR BLA_VENDOR STREQUAL "All")
+ set(_blas_nvhpc_lib "blas")
- # Check for OpenMP support, VIA BLA_VENDOR of eml_mt
- if(BLA_VENDOR MATCHES "_mt")
- set(BLAS_EML_LIB "${BLAS_EML_LIB}_mt")
- endif()
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_nvhpc_lib "_ilp64")
+ elseif(_blas_sizeof_integer EQUAL 4)
+ string(APPEND _blas_nvhpc_lib "_lp64")
+ endif()
- if(NOT BLAS_LIBRARIES)
+ if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "${BLAS_EML_LIB}"
+ "${_blas_nvhpc_lib}"
""
""
""
)
endif()
-endif()
+ # an additional check for NVHPC 2020
+ # which does not have differentiation
+ # between lp64 and ilp64 modes
+ if(NOT BLAS_LIBRARIES AND NOT _blas_sizeof_integer EQUAL 8)
+ set(_blas_nvhpc_lib "blas")
-# Fujitsu SSL2 Library?
-if(NOT BLAS_LIBRARIES
- AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All"))
- if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP")
- set(_ssl2_suffix BLAMP)
- else()
- set(_ssl2_suffix)
- endif()
- check_blas_libraries(
- BLAS_LIBRARIES
- BLAS
- sgemm
- "-SSL2${_ssl2_suffix}"
- ""
- ""
- ""
- ""
- )
- if(BLAS_LIBRARIES)
- set(BLAS_LINKER_FLAGS "-SSL2${_ssl2_suffix}")
- set(_blas_fphsa_req_var BLAS_LINKER_FLAGS)
+ check_blas_libraries(
+ BLAS_LIBRARIES
+ BLAS
+ sgemm
+ ""
+ "${_blas_nvhpc_lib}"
+ ""
+ ""
+ ""
+ )
endif()
- unset(_ssl2_suffix)
+
+ unset(_blas_nvhpc_lib)
endif()
# Generic BLAS library?
if(BLA_VENDOR STREQUAL "Generic" OR
- BLA_VENDOR STREQUAL "NVHPC" OR
BLA_VENDOR STREQUAL "All")
+ set(_blas_generic_lib "blas")
+
+ if(_blas_sizeof_integer EQUAL 8)
+ string(APPEND _blas_generic_lib "64")
+ endif()
+
if(NOT BLAS_LIBRARIES)
check_blas_libraries(
BLAS_LIBRARIES
BLAS
sgemm
""
- "blas"
+ "${_blas_generic_lib}"
""
""
""
)
endif()
+
+ unset(_blas_generic_lib)
endif()
# On compilers that implicitly link BLAS (i.e. CrayPrgEnv) we used a
@@ -1163,3 +1338,6 @@ if(NOT BLA_F95)
endif()
_add_blas_target()
+unset(_blas_fphsa_req_var)
+unset(_blas_sizeof_integer)
+unset(_BLAS_LIBRARIES)
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 89b8c997c..d22a6765e 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -742,6 +742,19 @@ elseif(NOT CUDAToolkit_FIND_QUIETLY)
message(STATUS "Unable to find cuda_runtime.h in \"${CUDAToolkit_TARGET_DIR}/include\" for CUDAToolkit_INCLUDE_DIR.")
endif()
+# The NVHPC layout moves math library headers and libraries to a sibling directory.
+# Create a separate variable so this directory can be selectively added to math targets.
+if(NOT EXISTS "${CUDAToolkit_INCLUDE_DIR}/cublas_v2.h")
+ set(CUDAToolkit_MATH_INCLUDE_DIR "${CUDAToolkit_TARGET_DIR}/../../math_libs/include")
+ cmake_path(NORMAL_PATH CUDAToolkit_MATH_INCLUDE_DIR)
+ if(NOT EXISTS "${CUDAToolkit_MATH_INCLUDE_DIR}/cublas_v2.h")
+ if(NOT CUDAToolkit_FIND_QUIETLY)
+ message(STATUS "Unable to find cublas_v2.h in either \"${CUDAToolkit_INCLUDE_DIR}\" or \"${CUDAToolkit_MATH_INCLUDE_DIR}\"")
+ endif()
+ unset(CUDAToolkit_MATH_INCLUDE_DIR)
+ endif()
+endif()
+
if(CUDAToolkit_NVCC_EXECUTABLE AND
CMAKE_CUDA_COMPILER_VERSION AND
CUDAToolkit_NVCC_EXECUTABLE STREQUAL CMAKE_CUDA_COMPILER)
@@ -844,14 +857,23 @@ if(CUDAToolkit_FOUND)
HINTS ${CUDAToolkit_LIBRARY_DIR}
ENV CUDA_PATH
PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs
+ # Support NVHPC splayed math library layout
+ ../../math_libs/${CUDAToolkit_VERSION_MAJOR}.${CUDAToolkit_VERSION_MINOR}/lib64
+ ../../math_libs/lib64
)
mark_as_advanced(CUDA_${lib_name}_LIBRARY)
if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY)
- add_library(CUDA::${lib_name} IMPORTED INTERFACE)
+ add_library(CUDA::${lib_name} UNKNOWN IMPORTED)
target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}")
- target_link_libraries(CUDA::${lib_name} INTERFACE "${CUDA_${lib_name}_LIBRARY}")
+ if(DEFINED CUDAToolkit_MATH_INCLUDE_DIR)
+ string(FIND ${CUDA_${lib_name}_LIBRARY} "math_libs" math_libs)
+ if(NOT ${math_libs} EQUAL -1)
+ target_include_directories(CUDA::${lib_name} SYSTEM INTERFACE "${CUDAToolkit_MATH_INCLUDE_DIR}")
+ endif()
+ endif()
+ set_property(TARGET CUDA::${lib_name} PROPERTY IMPORTED_LOCATION "${CUDA_${lib_name}_LIBRARY}")
foreach(dep ${arg_DEPS})
if(TARGET CUDA::${dep})
target_link_libraries(CUDA::${lib_name} INTERFACE CUDA::${dep})
diff --git a/Modules/FindFLTK.cmake b/Modules/FindFLTK.cmake
index bab72560d..d54d2f68b 100644
--- a/Modules/FindFLTK.cmake
+++ b/Modules/FindFLTK.cmake
@@ -152,13 +152,17 @@ if(NOT FLTK_DIR)
endif()
# Check if FLTK was built using CMake
-if(EXISTS ${FLTK_DIR}/FLTKConfig.cmake)
- set(FLTK_BUILT_WITH_CMAKE 1)
-endif()
+foreach(fltk_include IN LISTS FLTK_DIR)
+ if(EXISTS "${fltk_include}/FLTKConfig.cmake")
+ set(FLTK_BUILT_WITH_CMAKE 1)
+ set(FLTK_CMAKE_PATH "${fltk_include}/FLTKConfig.cmake")
+ break()
+ endif()
+endforeach()
if(FLTK_BUILT_WITH_CMAKE)
set(FLTK_FOUND 1)
- include(${FLTK_DIR}/FLTKConfig.cmake)
+ include("${FLTK_CMAKE_PATH}")
# Fluid
if(FLUID_COMMAND)
diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake
index 2770c604d..dd0975d39 100644
--- a/Modules/FindGLUT.cmake
+++ b/Modules/FindGLUT.cmake
@@ -41,8 +41,43 @@ Also defined, but not for general use are:
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-if (WIN32)
+function(_add_glut_target_simple)
+ if(TARGET GLUT::GLUT)
+ return()
+ endif()
+ add_library(GLUT::GLUT INTERFACE IMPORTED)
+ if(GLUT_INCLUDE_DIRS)
+ target_include_directories(GLUT::GLUT SYSTEM
+ INTERFACE "${GLUT_INCLUDE_DIRS}")
+ endif()
+ if(GLUT_LIBRARIES)
+ target_link_libraries(GLUT::GLUT INTERFACE ${GLUT_LIBRARIES})
+ endif()
+ if(GLUT_LDFLAGS)
+ target_link_options(GLUT::GLUT INTERFACE ${GLUT_LDFLAGS})
+ endif()
+ if(GLUT_CFLAGS)
+ separate_arguments(GLUT_CFLAGS_SPLIT UNIX_COMMAND "${GLUT_CFLAGS}")
+ target_compile_options(GLUT::GLUT INTERFACE ${GLUT_CFLAGS_SPLIT})
+ endif()
+
+ set_property(TARGET GLUT::GLUT APPEND PROPERTY
+ IMPORTED_LOCATION "${GLUT_glut_LIBRARY}")
+endfunction()
+
+find_package(PkgConfig)
+if(PKG_CONFIG_FOUND)
+ pkg_check_modules(GLUT glut)
+ if(GLUT_FOUND)
+ _add_glut_target_simple()
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND)
+ return()
+ endif()
+endif()
+
+if(WIN32)
find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h
PATHS ${GLUT_ROOT_PATH}/include )
find_library( GLUT_glut_LIBRARY_RELEASE NAMES glut glut32 freeglut
@@ -57,85 +92,75 @@ if (WIN32)
)
mark_as_advanced(GLUT_glut_LIBRARY_RELEASE GLUT_glut_LIBRARY_DEBUG)
select_library_configurations(GLUT_glut)
-else ()
-
- if (APPLE)
- find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
- find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX")
- find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX")
- mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY)
-
- if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa)
- add_library(GLUT::Cocoa UNKNOWN IMPORTED)
- # Cocoa should always be a Framework, but we check to make sure.
- if(GLUT_cocoa_LIBRARY MATCHES "/([^/]+)\\.framework$")
- set(_glut_cocoa "${GLUT_cocoa_LIBRARY}/${CMAKE_MATCH_1}")
- if(EXISTS "${_glut_cocoa}.tbd")
- string(APPEND _glut_cocoa ".tbd")
- endif()
- set_target_properties(GLUT::Cocoa PROPERTIES
- IMPORTED_LOCATION "${_glut_cocoa}")
- else()
- set_target_properties(GLUT::Cocoa PROPERTIES
- IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}")
+elseif(APPLE)
+ find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR})
+ find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX")
+ find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX")
+ mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY)
+
+ if(GLUT_cocoa_LIBRARY AND NOT TARGET GLUT::Cocoa)
+ add_library(GLUT::Cocoa UNKNOWN IMPORTED)
+ # Cocoa should always be a Framework, but we check to make sure.
+ if(GLUT_cocoa_LIBRARY MATCHES "/([^/]+)\\.framework$")
+ set(_glut_cocoa "${GLUT_cocoa_LIBRARY}/${CMAKE_MATCH_1}")
+ if(EXISTS "${_glut_cocoa}.tbd")
+ string(APPEND _glut_cocoa ".tbd")
endif()
- endif()
- else ()
-
- if (BEOS)
-
- set(_GLUT_INC_DIR /boot/develop/headers/os/opengl)
- set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86)
-
+ set_target_properties(GLUT::Cocoa PROPERTIES
+ IMPORTED_LOCATION "${_glut_cocoa}")
else()
-
- find_library( GLUT_Xi_LIBRARY Xi
- /usr/openwin/lib
- )
- mark_as_advanced(GLUT_Xi_LIBRARY)
-
- find_library( GLUT_Xmu_LIBRARY Xmu
- /usr/openwin/lib
- )
- mark_as_advanced(GLUT_Xmu_LIBRARY)
-
- if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi)
- add_library(GLUT::Xi UNKNOWN IMPORTED)
- set_target_properties(GLUT::Xi PROPERTIES
- IMPORTED_LOCATION "${GLUT_Xi_LIBRARY}")
- endif()
-
- if(GLUT_Xmu_LIBRARY AND NOT TARGET GLUT::Xmu)
- add_library(GLUT::Xmu UNKNOWN IMPORTED)
- set_target_properties(GLUT::Xmu PROPERTIES
- IMPORTED_LOCATION "${GLUT_Xmu_LIBRARY}")
- endif()
-
- endif ()
-
- find_path( GLUT_INCLUDE_DIR GL/glut.h
- /usr/include/GL
- /usr/openwin/share/include
- /usr/openwin/include
- /opt/graphics/OpenGL/include
- /opt/graphics/OpenGL/contrib/libglut
- ${_GLUT_INC_DIR}
+ set_target_properties(GLUT::Cocoa PROPERTIES
+ IMPORTED_LOCATION "${GLUT_cocoa_LIBRARY}")
+ endif()
+ endif()
+else()
+ if(BEOS)
+ set(_GLUT_INC_DIR /boot/develop/headers/os/opengl)
+ set(_GLUT_glut_LIB_DIR /boot/develop/lib/x86)
+ else()
+ find_library( GLUT_Xi_LIBRARY Xi
+ /usr/openwin/lib
)
+ mark_as_advanced(GLUT_Xi_LIBRARY)
- find_library( GLUT_glut_LIBRARY glut
+ find_library( GLUT_Xmu_LIBRARY Xmu
/usr/openwin/lib
- ${_GLUT_glut_LIB_DIR}
)
- mark_as_advanced(GLUT_glut_LIBRARY)
+ mark_as_advanced(GLUT_Xmu_LIBRARY)
- unset(_GLUT_INC_DIR)
- unset(_GLUT_glut_LIB_DIR)
+ if(GLUT_Xi_LIBRARY AND NOT TARGET GLUT::Xi)
+ add_library(GLUT::Xi UNKNOWN IMPORTED)
+ set_target_properties(GLUT::Xi PROPERTIES
+ IMPORTED_LOCATION "${GLUT_Xi_LIBRARY}")
+ endif()
+
+ if(GLUT_Xmu_LIBRARY AND NOT TARGET GLUT::Xmu)
+ add_library(GLUT::Xmu UNKNOWN IMPORTED)
+ set_target_properties(GLUT::Xmu PROPERTIES
+ IMPORTED_LOCATION "${GLUT_Xmu_LIBRARY}")
+ endif()
endif ()
-endif ()
+ find_path( GLUT_INCLUDE_DIR GL/glut.h
+ /usr/include/GL
+ /usr/openwin/share/include
+ /usr/openwin/include
+ /opt/graphics/OpenGL/include
+ /opt/graphics/OpenGL/contrib/libglut
+ ${_GLUT_INC_DIR}
+ )
+
+ find_library( GLUT_glut_LIBRARY glut
+ /usr/openwin/lib
+ ${_GLUT_glut_LIB_DIR}
+ )
+
+ unset(_GLUT_INC_DIR)
+ unset(_GLUT_glut_LIB_DIR)
+endif()
+mark_as_advanced(GLUT_glut_LIBRARY)
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_glut_LIBRARY GLUT_INCLUDE_DIR)
if (GLUT_FOUND)
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index e33535513..6cadadb90 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -161,6 +161,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
# scope somewhere else. We can't rely on it because different components may
# have been requested for this call.
set(HDF5_FOUND OFF)
+set(HDF5_LIBRARIES)
+set(HDF5_HL_LIBRARIES)
# List of the valid HDF5 components
set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran)
@@ -560,7 +562,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
set(HDF5_${_lang}_FOUND TRUE)
endif()
if(HDF5_FIND_HL)
- get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} )
+ get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} )
if (NOT _hdf5_lang_hl_location)
get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf})
if (NOT _hdf5_hl_lang_location)
@@ -586,6 +588,9 @@ if(NOT HDF5_FOUND)
set(HDF5_COMPILER_NO_INTERROGATE TRUE)
# Only search for languages we've enabled
foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
+ set(HDF5_${_lang}_LIBRARIES)
+ set(HDF5_${_lang}_HL_LIBRARIES)
+
# First check to see if our regular compiler is one of wrappers
if(_lang STREQUAL "C")
_HDF5_test_regular_compiler_C(
@@ -811,6 +816,9 @@ if( NOT HDF5_FOUND )
endif()
foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
+ set(HDF5_${_lang}_LIBRARIES)
+ set(HDF5_${_lang}_HL_LIBRARIES)
+
# The "main" library.
set(_hdf5_main_library "")
diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake
index 2bb49adec..1bae825a5 100644
--- a/Modules/FindICU.cmake
+++ b/Modules/FindICU.cmake
@@ -172,7 +172,7 @@ function(_ICU_FIND)
DOC "ICU ${program} executable"
NO_PACKAGE_ROOT_PATH
)
- mark_as_advanced(cache_var)
+ mark_as_advanced("${cache_var}")
set("${program_var}" "${${cache_var}}" PARENT_SCOPE)
endforeach()
@@ -301,7 +301,7 @@ function(_ICU_FIND)
HINTS ${icu_roots}
PATH_SUFFIXES ${icu_data_suffixes}
DOC "ICU ${data} data file")
- mark_as_advanced(cache_var)
+ mark_as_advanced("${cache_var}")
set("${data_var}" "${${cache_var}}" PARENT_SCOPE)
endforeach()
diff --git a/Modules/FindJasper.cmake b/Modules/FindJasper.cmake
index 729a50350..9a62669f2 100644
--- a/Modules/FindJasper.cmake
+++ b/Modules/FindJasper.cmake
@@ -5,43 +5,86 @@
FindJasper
----------
-Try to find the Jasper JPEG2000 library
+Find the Jasper JPEG2000 library.
-Once done this will define
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
-::
+``Jasper::Jasper``
+ The jasper library, if found.
- JASPER_FOUND - system has Jasper
- JASPER_INCLUDE_DIR - the Jasper include directory
- JASPER_LIBRARIES - the libraries needed to use Jasper
- JASPER_VERSION_STRING - the version of Jasper found (since CMake 2.8.8)
-#]=======================================================================]
+Result Variables
+^^^^^^^^^^^^^^^^
-find_path(JASPER_INCLUDE_DIR jasper/jasper.h)
+This module defines the following variables:
+
+``JASPER_FOUND``
+ system has Jasper
+``JASPER_INCLUDE_DIRS``
+ .. versionadded:: 3.22
+
+ the Jasper include directory
+``JASPER_LIBRARIES``
+ the libraries needed to use Jasper
+``JASPER_VERSION_STRING``
+ the version of Jasper found
+
+Cache variables
+^^^^^^^^^^^^^^^
-if (NOT JASPER_LIBRARIES)
- find_package(JPEG)
+The following cache variables may also be set:
- find_library(JASPER_LIBRARY_RELEASE NAMES jasper libjasper)
- find_library(JASPER_LIBRARY_DEBUG NAMES jasperd)
+``JASPER_INCLUDE_DIR``
+ where to find jasper/jasper.h, etc.
+``JASPER_LIBRARY_RELEASE``
+ where to find the Jasper library (optimized).
+``JASPER_LIBARRY_DEBUG``
+ where to find the Jasper library (debug).
+#]=======================================================================]
- include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
- SELECT_LIBRARY_CONFIGURATIONS(JASPER)
-endif ()
+find_path(JASPER_INCLUDE_DIR jasper/jasper.h)
+mark_as_advanced(JASPER_INCLUDE_DIR)
-if (JASPER_INCLUDE_DIR AND EXISTS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h")
- file(STRINGS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" jasper_version_str REGEX "^#define[\t ]+JAS_VERSION[\t ]+\".*\".*")
+if(NOT JASPER_LIBRARIES)
+ find_package(JPEG)
+ find_library(JASPER_LIBRARY_RELEASE NAMES jasper libjasper)
+ find_library(JASPER_LIBRARY_DEBUG NAMES jasperd)
+ include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
+ select_library_configurations(JASPER)
+endif()
- string(REGEX REPLACE "^#define[\t ]+JAS_VERSION[\t ]+\"([^\"]+)\".*" "\\1" JASPER_VERSION_STRING "${jasper_version_str}")
-endif ()
+if(JASPER_INCLUDE_DIR AND EXISTS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h")
+ file(STRINGS "${JASPER_INCLUDE_DIR}/jasper/jas_config.h" jasper_version_str REGEX "^#define[\t ]+JAS_VERSION[\t ]+\".*\".*")
+ string(REGEX REPLACE "^#define[\t ]+JAS_VERSION[\t ]+\"([^\"]+)\".*" "\\1" JASPER_VERSION_STRING "${jasper_version_str}")
+endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Jasper
+find_package_handle_standard_args(Jasper
REQUIRED_VARS JASPER_LIBRARIES JASPER_INCLUDE_DIR JPEG_LIBRARIES
VERSION_VAR JASPER_VERSION_STRING)
-if (JASPER_FOUND)
- set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES} )
-endif ()
-
-mark_as_advanced(JASPER_INCLUDE_DIR)
+if(JASPER_FOUND)
+ set(JASPER_LIBRARIES ${JASPER_LIBRARIES} ${JPEG_LIBRARIES})
+ set(JASPER_INCLUDE_DIRS ${JASPER_INCLUDE_DIR})
+ if(NOT TARGET Jasper::Jasper)
+ add_library(Jasper::Jasper UNKNOWN IMPORTED)
+ if(JASPER_INCLUDE_DIRS)
+ set_target_properties(Jasper::Jasper PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${JASPER_INCLUDE_DIRS}")
+ endif()
+ if(EXISTS "${JASPER_LIBRARY_RELEASE}")
+ set_property(TARGET Jasper::Jasper APPEND PROPERTY
+ IMPORTED CONFIGURATION RELEASE)
+ set_target_properties(Jasper::Jasper PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+ IMPORTED_LOCATION "${JASPER_LIBRARY_RELEASE}")
+ endif()
+ if(EXISTS "${JASPER_LIBRARY_DEBUG}")
+ set_property(TARGET Jasper::Jasper APPEND PROPERTY
+ IMPORTED CONFIGURATION DEBUG)
+ set_target_properties(Jasper::Jasper PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+ IMPORTED_LOCATION "${JASPER_LIBRARY_DEBUG}")
+ endif()
+ endif()
+endif()
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index 3146e06d4..5540965e5 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -35,6 +35,19 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a LAPACK library first
and if one is found that is preferred
+``BLA_SIZEOF_INTEGER``
+ .. versionadded:: 3.22
+
+ Specify the BLAS/LAPACK library integer size:
+
+ ``4``
+ Search for a BLAS/LAPACK with 32-bit integer interfaces.
+ ``8``
+ Search for a BLAS/LAPACK with 64-bit integer interfaces.
+ ``ANY``
+ Search for any BLAS/LAPACK.
+ Most likely, a BLAS/LAPACK with 32-bit integer interfaces will be found.
+
Imported targets
^^^^^^^^^^^^^^^^
@@ -168,9 +181,9 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl
list(APPEND _libraries "${_library}")
else()
string(REGEX REPLACE "[^A-Za-z0-9]" "_" _lib_var "${_library}")
- set(_combined_name ${_combined_name}_${_lib_var})
+ string(APPEND _combined_name "_${_lib_var}")
if(NOT "${_deps}" STREQUAL "")
- set(_combined_name ${_combined_name}_deps)
+ string(APPEND _combined_name "_deps")
endif()
if(_libraries_work)
find_library(${_prefix}_${_lib_var}_LIBRARY
@@ -188,7 +201,7 @@ function(CHECK_LAPACK_LIBRARIES LIBRARIES _prefix _name _flags _list _deps _addl
foreach(_flag ${_flags})
string(REGEX REPLACE "[^A-Za-z0-9]" "_" _flag_var "${_flag}")
- set(_combined_name ${_combined_name}_${_flag_var})
+ string(APPEND _combined_name "_${_flag_var}")
endforeach()
if(_libraries_work)
# Test this combination of libraries.
@@ -247,6 +260,17 @@ if(NOT (CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_CO
"FindLAPACK requires Fortran, C, or C++ to be enabled.")
endif()
+if(NOT BLA_SIZEOF_INTEGER)
+ # in the reality we do not know which API of BLAS/LAPACK is masked in library
+ set(_lapack_sizeof_integer "ANY")
+elseif((BLA_SIZEOF_INTEGER STREQUAL "ANY") OR
+ (BLA_SIZEOF_INTEGER STREQUAL "4") OR
+ (BLA_SIZEOF_INTEGER STREQUAL "8"))
+ set(_lapack_sizeof_integer ${BLA_SIZEOF_INTEGER})
+else()
+ message(FATAL_ERROR "BLA_SIZEOF_INTEGER can have only <no value>, ANY, 4, or 8 values")
+endif()
+
# Load BLAS
if(NOT LAPACK_NOT_FOUND_MESSAGE)
_lapack_find_dependency(BLAS)
@@ -288,17 +312,23 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
_lapack_find_dependency(Threads)
- if(BLA_VENDOR MATCHES "_64ilp")
+ if(_lapack_sizeof_integer EQUAL 8)
set(LAPACK_mkl_ILP_MODE "ilp64")
- else()
+ elseif(_lapack_sizeof_integer EQUAL 4)
set(LAPACK_mkl_ILP_MODE "lp64")
+ else()
+ if(BLA_VENDOR MATCHES "_64ilp")
+ set(LAPACK_mkl_ILP_MODE "ilp64")
+ else()
+ set(LAPACK_mkl_ILP_MODE "lp64")
+ endif()
endif()
set(LAPACK_SEARCH_LIBS "")
if(BLA_F95)
set(LAPACK_mkl_SEARCH_SYMBOL "cheev_f95")
- set(_LIBRARIES LAPACK95_LIBRARIES)
+ set(_LAPACK_LIBRARIES LAPACK95_LIBRARIES)
set(_BLAS_LIBRARIES ${BLAS95_LIBRARIES})
# old
@@ -311,7 +341,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
"mkl_lapack95_${LAPACK_mkl_ILP_MODE}")
else()
set(LAPACK_mkl_SEARCH_SYMBOL "cheev")
- set(_LIBRARIES LAPACK_LIBRARIES)
+ set(_LAPACK_LIBRARIES LAPACK_LIBRARIES)
set(_BLAS_LIBRARIES ${BLAS_LIBRARIES})
# old and new >= 10.3
@@ -350,10 +380,10 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
"lib/${LAPACK_mkl_ARCH_NAME}"
)
- # First try empty lapack libs
- if(NOT ${_LIBRARIES})
+ # First try empty lapack libs (implicitly linked or automatic from BLAS)
+ if(NOT ${_LAPACK_LIBRARIES})
check_lapack_libraries(
- ${_LIBRARIES}
+ ${_LAPACK_LIBRARIES}
LAPACK
${LAPACK_mkl_SEARCH_SYMBOL}
""
@@ -363,18 +393,23 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
"${LAPACK_mkl_LIB_PATH_SUFFIXES}"
"${_BLAS_LIBRARIES}"
)
+ if(LAPACK_WORKS AND NOT _BLAS_LIBRARIES)
+ # Give a more helpful "found" message
+ set(LAPACK_WORKS "implicitly linked")
+ set(_lapack_fphsa_req_var LAPACK_WORKS)
+ endif()
endif()
# Then try the search libs
- foreach(IT ${LAPACK_SEARCH_LIBS})
- string(REPLACE " " ";" SEARCH_LIBS ${IT})
- if(NOT ${_LIBRARIES})
+ foreach(_search ${LAPACK_SEARCH_LIBS})
+ string(REPLACE " " ";" _search ${_search})
+ if(NOT ${_LAPACK_LIBRARIES})
check_lapack_libraries(
- ${_LIBRARIES}
+ ${_LAPACK_LIBRARIES}
LAPACK
${LAPACK_mkl_SEARCH_SYMBOL}
""
- "${SEARCH_LIBS}"
+ "${_search}"
"${CMAKE_THREAD_LIBS_INIT};${LAPACK_mkl_LM};${LAPACK_mkl_LDL}"
"${LAPACK_mkl_MKLROOT}"
"${LAPACK_mkl_LIB_PATH_SUFFIXES}"
@@ -383,6 +418,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
endif()
endforeach()
+ unset(_search)
unset(LAPACK_mkl_ILP_MODE)
unset(LAPACK_mkl_SEARCH_SYMBOL)
unset(LAPACK_mkl_LM)
@@ -412,48 +448,70 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
# FlexiBLAS? (http://www.mpi-magdeburg.mpg.de/mpcsc/software/FlexiBLAS/)
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "FlexiBLAS" OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_flexiblas_lib "flexiblas")
+
+ if(_lapack_sizeof_integer EQUAL 8)
+ string(APPEND _lapack_flexiblas_lib "64")
+ endif()
+
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
- "flexiblas"
+ "${_lapack_flexiblas_lib}"
""
""
""
"${BLAS_LIBRARIES}"
)
+
+ unset(_lapack_flexiblas_lib)
endif()
# OpenBLAS? (http://www.openblas.net)
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "OpenBLAS" OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_openblas_lib "openblas")
+
+ if(_lapack_sizeof_integer EQUAL 8)
+ string(APPEND _lapack_openblas_lib "64")
+ endif()
+
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
- "openblas"
+ "${_lapack_openblas_lib}"
""
""
""
"${BLAS_LIBRARIES}"
)
+
+ unset(_lapack_openblas_lib)
endif()
# ArmPL? (https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux/arm-performance-libraries)
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All"))
# Check for 64bit Integer support
- if(BLA_VENDOR MATCHES "_ilp64")
+ if(_lapack_sizeof_integer EQUAL 8)
set(LAPACK_armpl_LIB "armpl_ilp64")
- else()
+ elseif(_lapack_sizeof_integer EQUAL 4)
set(LAPACK_armpl_LIB "armpl_lp64")
+ else()
+ if(BLA_VENDOR MATCHES "_ilp64")
+ set(LAPACK_armpl_LIB "armpl_ilp64")
+ else()
+ set(LAPACK_armpl_LIB "armpl_lp64")
+ endif()
endif()
# Check for OpenMP support, VIA BLA_VENDOR of Arm_mp or Arm_ipl64_mp
if(BLA_VENDOR MATCHES "_mp")
- set(LAPACK_armpl_LIB "${LAPACK_armpl_LIB}_mp")
+ string(APPEND LAPACK_armpl_LIB "_mp")
endif()
check_lapack_libraries(
@@ -472,17 +530,50 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
# FLAME's blis library? (https://github.com/flame/blis)
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All"))
+ if(_lapack_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "FLAME")
+ message(FATAL_ERROR "libFLAME does not support Int64 type")
+ endif()
+ else()
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "flame"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
+ endif()
+
+ # LAPACK in SCSL library? (SGI/Cray Scientific Library)
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "SCSL" OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_scsl_lib "scs")
+
+ if(_lapack_sizeof_integer EQUAL 8)
+ string(APPEND _lapack_scsl_lib "_i8")
+ endif()
+ # Check for OpenMP support, VIA BLA_VENDOR of scs_mp
+ if(BLA_VENDOR MATCHES "_mp")
+ string(APPEND _lapack_scsl_lib "_mp")
+ endif()
+
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
- "flame"
+ "${_lapack_scsl_lib}"
""
""
""
"${BLAS_LIBRARIES}"
)
+ unset(_lapack_scsl_lib)
endif()
# BLAS in acml library?
@@ -495,105 +586,116 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
# Apple LAPACK library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "Apple" OR BLA_VENDOR STREQUAL "All"))
- check_lapack_libraries(
- LAPACK_LIBRARIES
- LAPACK
- cheev
- ""
- "Accelerate"
- ""
- ""
- ""
- "${BLAS_LIBRARIES}"
- )
+ if(_lapack_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "Apple")
+ message(FATAL_ERROR "Accelerate Framework does not support Int64 type")
+ endif()
+ else()
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "Accelerate"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
endif()
# Apple NAS (vecLib) library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR STREQUAL "NAS" OR BLA_VENDOR STREQUAL "All"))
- check_lapack_libraries(
- LAPACK_LIBRARIES
- LAPACK
- cheev
- ""
- "vecLib"
- ""
- ""
- ""
- "${BLAS_LIBRARIES}"
- )
+ if(_lapack_sizeof_integer EQUAL 8)
+ if(BLA_VENDOR STREQUAL "NAS")
+ message(FATAL_ERROR "Accelerate Framework does not support Int64 type")
+ endif()
+ else()
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "vecLib"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
endif()
# Elbrus Math Library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All"))
-
- set(LAPACK_EML_LIB "eml")
-
- # Check for OpenMP support, VIA BLA_VENDOR of eml_mt
- if(BLA_VENDOR MATCHES "_mt")
- set(LAPACK_EML_LIB "${LAPACK_EML_LIB}_mt")
+ if(BLAS_LIBRARIES MATCHES "eml.+")
+ set(LAPACK_LIBRARIES ${BLAS_LIBRARIES})
endif()
-
- check_lapack_libraries(
- LAPACK_LIBRARIES
- LAPACK
- cheev
- ""
- "${LAPACK_EML_LIB}"
- ""
- ""
- ""
- "${BLAS_LIBRARIES}"
- )
endif()
# Fujitsu SSL2 Library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR MATCHES "Fujitsu_SSL2" OR BLA_VENDOR STREQUAL "All"))
- if(BLA_VENDOR STREQUAL "Fujitsu_SSL2BLAMP")
- set(_ssl2_suffix BLAMP)
- else()
- set(_ssl2_suffix)
- endif()
- set(_ssl2_blas)
- if(BLAS_LIBRARIES STREQUAL "")
- set(_ssl2_blas "${BLAS_LINKER_FLAGS}")
- else()
- set(_ssl2_blas "${BLAS_LIBRARIES} ${BLAS_LINKER_FLAGS}")
+ if(BLAS_LIBRARIES MATCHES "fjlapack.+")
+ set(LAPACK_LIBRARIES ${BLAS_LIBRARIES})
+ set(LAPACK_LINKER_FLAGS ${BLAS_LINKER_FLAGS})
endif()
- check_lapack_libraries(
- LAPACK_LIBRARIES
- LAPACK
- cheev
- "-SSL2${_ssl2_suffix}"
- ""
- ""
- ""
- ""
- "${_ssl2_blas}"
- )
- if(LAPACK_LIBRARIES)
- set(LAPACK_LINKER_FLAGS "-SSL2${_ssl2_suffix}")
- set(_lapack_fphsa_req_var LAPACK_LINKER_FLAGS)
+ endif()
+
+ # LAPACK in IBM ESSL library?
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All"))
+ if(BLAS_LIBRARIES MATCHES "essl.+")
+ set(LAPACK_LIBRARIES ${BLAS_LIBRARIES})
endif()
- unset(_ssl2_suffix)
endif()
# NVHPC Library?
+
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_nvhpc_lib "lapack")
+
+ if(_lapack_sizeof_integer EQUAL 8)
+ string(APPEND _lapack_nvhpc_lib "_ilp64")
+ elseif(_lapack_sizeof_integer EQUAL 4)
+ string(APPEND _lapack_nvhpc_lib "_lp64")
+ endif()
+
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
- "lapack"
+ "${_lapack_nvhpc_lib}"
"-fortranlibs"
""
""
"${BLAS_LIBRARIES}"
)
+
+ # an additional check for NVHPC 2020
+ # which does not have differentiation
+ # between lp64 and ilp64 modes
+ if(NOT LAPACK_LIBRARIES AND NOT _lapack_sizeof_integer EQUAL 8)
+ set(_lapack_nvhpc_lib "lapack")
+
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "${_lapack_nvhpc_lib}"
+ "-fortranlibs"
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ endif()
+
+ unset(_lapack_nvhpc_lib)
endif()
# Generic LAPACK library?
@@ -601,6 +703,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
AND (BLA_VENDOR STREQUAL "Generic"
OR BLA_VENDOR STREQUAL "ATLAS"
OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_generic_lib "lapack")
if(BLA_STATIC)
# We do not know for sure how the LAPACK reference implementation
# is built on this host. Guess typical dependencies.
@@ -608,18 +711,25 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
else()
set(_lapack_generic_deps "")
endif()
+
+ if(_lapack_sizeof_integer EQUAL 8)
+ string(APPEND _lapack_generic_lib "64")
+ endif()
+
check_lapack_libraries(
LAPACK_LIBRARIES
LAPACK
cheev
""
- "lapack"
+ "${_lapack_generic_lib}"
"${_lapack_generic_deps}"
""
""
"${BLAS_LIBRARIES}"
)
+
unset(_lapack_generic_deps)
+ unset(_lapack_generic_lib)
endif()
endif()
@@ -646,3 +756,6 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
endif()
_add_lapack_target()
+unset(_lapack_fphsa_req_var)
+unset(_lapack_sizeof_integer)
+unset(_LAPACK_LIBRARIES)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index d8f033408..c974d3388 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -105,7 +105,7 @@ This module performs a four step search for an MPI implementation:
1. Search for ``MPIEXEC_EXECUTABLE`` and, if found, use its base directory.
2. Check if the compiler has MPI support built-in. This is the case if the user passed a
- compiler wrapper as ``CMAKE_<LANG>_COMPILER`` or if they're on a Cray system.
+ compiler wrapper as ``CMAKE_<LANG>_COMPILER`` or if they use Cray system compiler wrappers.
3. Attempt to find an MPI compiler wrapper and determine the compiler information from it.
4. Try to find an MPI implementation that does not ship such a wrapper by guessing settings.
Currently, only Microsoft MPI and MPICH2 on Windows are supported.
@@ -267,6 +267,7 @@ cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW) # if IN_LIST
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package(PkgConfig QUIET)
# Generic compiler names
set(_MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r)
@@ -333,6 +334,11 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95
mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r
mpixlf mpixlf_r mpxlf mpxlf_r)
+# Cray Compiler names
+set(_MPI_Cray_C_COMPILER_NAMES cc)
+set(_MPI_Cray_CXX_COMPILER_NAMES CC)
+set(_MPI_Cray_Fortran_COMPILER_NAMES ftn)
+
# Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler,
# attempt all of them.
# By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper
@@ -488,6 +494,26 @@ function (_MPI_interrogate_compiler LANG)
endif()
endif()
+ # Cray compiler wrappers come usually without a separate mpicc/c++/ftn, but offer
+ # --cray-print-opts=...
+ if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ _MPI_check_compiler(${LANG} "--cray-print-opts=cflags"
+ MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN)
+
+ if (MPI_COMPILER_RETURN EQUAL 0)
+ # Pass --no-as-needed so the mpi library is always linked. Otherwise, the
+ # Cray compiler wrapper puts an --as-needed flag around the mpi library,
+ # and it is not linked unless code directly refers to it.
+ _MPI_check_compiler(${LANG} "--no-as-needed;--cray-print-opts=libs"
+ MPI_LINK_CMDLINE MPI_COMPILER_RETURN)
+
+ if (NOT MPI_COMPILER_RETURN EQUAL 0)
+ unset(MPI_COMPILE_CMDLINE)
+ unset(MPI_LINK_CMDLINE)
+ endif()
+ endif()
+ endif()
+
# MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the
# -showme commands are more specialized.
if (NOT MPI_COMPILER_RETURN EQUAL 0)
@@ -1441,9 +1467,10 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
if(_MPI_FIND_${LANG})
if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS )
- set(MPI_CXX_SKIP_MPICXX FALSE CACHE BOOL "If true, the MPI-2 C++ bindings are disabled using definitions.")
+ option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE)
mark_as_advanced(MPI_CXX_SKIP_MPICXX)
endif()
+ _MPI_adjust_compile_definitions(${LANG})
if(NOT (MPI_${LANG}_LIB_NAMES AND (MPI_${LANG}_INCLUDE_PATH OR MPI_${LANG}_INCLUDE_DIRS OR MPI_${LANG}_COMPILER_INCLUDE_DIRS)))
set(MPI_${LANG}_TRIED_IMPLICIT FALSE)
set(MPI_${LANG}_WORKS_IMPLICIT FALSE)
@@ -1520,10 +1547,66 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
endif()
+ # We are on a Cray, environment identfier: PE_ENV is set (CRAY), and
+ # have NOT found an mpic++-like compiler wrapper (previous block),
+ # and we do NOT use the Cray cc/CC compiler wrappers as CC/CXX CMake
+ # compiler.
+ # So as a last resort, we now interrogate cc/CC/ftn for MPI flags.
+ if(DEFINED ENV{PE_ENV} AND NOT "${MPI_${LANG}_COMPILER}")
+ set(MPI_PINNED_COMPILER TRUE)
+ find_program(MPI_${LANG}_COMPILER
+ NAMES ${_MPI_Cray_${LANG}_COMPILER_NAMES}
+ PATH_SUFFIXES bin sbin
+ DOC "MPI compiler for ${LANG}"
+ )
+
+ # If we haven't made the implicit compiler test yet, perform it now.
+ if(NOT MPI_${LANG}_TRIED_IMPLICIT)
+ _MPI_create_imported_target(${LANG})
+ _MPI_check_lang_works(${LANG} TRUE)
+ endif()
+
+ set(MPI_${LANG}_WORKS_IMPLICIT TRUE)
+ _MPI_interrogate_compiler(${LANG})
+ endif()
+
if(NOT MPI_PINNED_COMPILER AND NOT MPI_${LANG}_WRAPPER_FOUND)
# If MPI_PINNED_COMPILER wasn't given, and the MPI compiler we potentially found didn't work, we withdraw it.
set(MPI_${LANG}_COMPILER "MPI_${LANG}_COMPILER-NOTFOUND" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE)
- if(NOT MPI_SKIP_GUESSING)
+
+ if(LANG STREQUAL "C")
+ set(_MPI_PKG "mpi-c")
+ elseif(LANG STREQUAL "CXX")
+ set(_MPI_PKG "mpi-cxx")
+ elseif(LANG STREQUAL "Fortran")
+ set(_MPI_PKG "mpi-fort")
+ else()
+ set(_MPI_PKG "")
+ endif()
+ if(_MPI_PKG AND PKG_CONFIG_FOUND)
+ pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}")
+ if("${MPI_${LANG}_PKG_FOUND}")
+ set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE)
+ set(MPI_${LANG}_INCLUDE_PATH ${MPI_${LANG}_PKG_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} include directories" FORCE)
+ set(MPI_${LANG}_LINK_FLAGS ${MPI_${LANG}_PKG_LDFLAGS} CACHE STRING "MPI ${LANG} linker flags" FORCE)
+ set(MPI_${LANG}_LIB_NAMES ${MPI_${LANG}_PKG_LIBRARIES} CACHE STRING "MPI ${LANG} libraries to link against" FORCE)
+ foreach(_MPI_LIB IN LISTS MPI_${LANG}_LIB_NAMES)
+ if(_MPI_LIB)
+ get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE)
+ get_filename_component(_MPI_LIB_NAME "${_MPI_LIB}" NAME)
+ get_filename_component(_MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY)
+ find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY
+ NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}"
+ HINTS ${_MPI_LIB_DIR}
+ DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI"
+ )
+ mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY)
+ endif()
+ endforeach()
+ endif()
+ endif()
+
+ if(NOT MPI_SKIP_GUESSING AND NOT "${MPI_${LANG}_PKG_FOUND}")
# For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the
# settings for C. An MPI distribution that is in this situation would be IBM Platform MPI.
if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND)
@@ -1548,7 +1631,6 @@ foreach(LANG IN ITEMS C CXX Fortran)
endif()
_MPI_assemble_libraries(${LANG})
- _MPI_adjust_compile_definitions(${LANG})
# We always create imported targets even if they're empty
_MPI_create_imported_target(${LANG})
diff --git a/Modules/FindMPI/test_mpi.c b/Modules/FindMPI/test_mpi.c
index 7c96d54a8..70d7e1d3e 100644
--- a/Modules/FindMPI/test_mpi.c
+++ b/Modules/FindMPI/test_mpi.c
@@ -7,15 +7,15 @@
#endif
#if defined(MPI_VERSION) && defined(MPI_SUBVERSION)
-const char mpiver_str[] = { 'I', 'N',
- 'F', 'O',
- ':', 'M',
- 'P', 'I',
- '-', 'V',
- 'E', 'R',
- '[', ('0' + MPI_VERSION),
- '.', ('0' + MPI_SUBVERSION),
- ']', '\0' };
+const static char mpiver_str[] = { 'I', 'N',
+ 'F', 'O',
+ ':', 'M',
+ 'P', 'I',
+ '-', 'V',
+ 'E', 'R',
+ '[', ('0' + MPI_VERSION),
+ '.', ('0' + MPI_SUBVERSION),
+ ']', '\0' };
#endif
int main(int argc, char* argv[])
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index e7cd834d9..0ca593e98 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -93,6 +93,33 @@ behavior:
additional versions of Matlab for the automatic retrieval of the installed
versions.
+Imported targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.22
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+``Matlab::mex``
+ The ``mex`` library, always available.
+
+``Matlab::mx``
+ The mx library of Matlab (arrays), always available.
+
+``Matlab::eng``
+ Matlab engine library. Available only if the ``ENG_LIBRARY`` component
+ is requested.
+
+``Matlab::mat``
+ Matlab matrix library. Available only if the ``MAT_LIBRARY`` component
+ is requested.
+
+``Matlab::MatlabEngine``
+ Matlab C++ engine library, always available for R2018a and newer.
+
+``Matlab::MatlabDataArray``
+ Matlab C++ data array library, always available for R2018a and newer.
+
Variables defined by the module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -451,7 +478,7 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio
if(matlabs_from_registry)
list(REMOVE_DUPLICATES matlabs_from_registry)
- list(SORT matlabs_from_registry)
+ list(SORT matlabs_from_registry COMPARE NATURAL)
list(REVERSE matlabs_from_registry)
endif()
@@ -495,7 +522,7 @@ macro(extract_matlab_versions_from_registry_brute_force matlab_versions)
# we order from more recent to older
if(matlab_supported_versions)
list(REMOVE_DUPLICATES matlab_supported_versions)
- list(SORT matlab_supported_versions)
+ list(SORT matlab_supported_versions COMPARE NATURAL)
list(REVERSE matlab_supported_versions)
endif()
@@ -1545,6 +1572,29 @@ if(_numbers_of_matlab_roots GREATER 0)
list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR)
list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING)
list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR)
+ elseif(DEFINED Matlab_FIND_VERSION)
+ foreach(_matlab_root_index RANGE 1 ${_numbers_of_matlab_roots} 3)
+ list(GET _matlab_possible_roots ${_matlab_root_index} _matlab_root_version)
+ if(_matlab_root_version VERSION_GREATER_EQUAL Matlab_FIND_VERSION)
+ set(_list_index ${_matlab_root_index})
+ break()
+ endif()
+ endforeach()
+
+ if(_list_index LESS 0)
+ set(_list_index 1)
+ endif()
+
+ math(EXPR _matlab_or_mcr_index "${_list_index} - 1")
+ math(EXPR _matlab_root_dir_index "${_list_index} + 1")
+ list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR)
+ list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING)
+ list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR)
+ # adding a warning in case of ambiguity
+ if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
+ " If this is not the desired behavior, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line")
+ endif()
else()
list(GET _matlab_possible_roots 0 Matlab_Or_MCR)
list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING)
@@ -1866,6 +1916,32 @@ if(Matlab_DATAARRAY_LIBRARY)
list(APPEND Matlab_LIBRARIES ${Matlab_DATAARRAY_LIBRARY})
endif()
+# internal
+# This small stub permits to add imported targets for the found MATLAB libraries
+function(_Matlab_add_imported_target _matlab_library_variable_name _matlab_library_target_name)
+ if(Matlab_${_matlab_library_variable_name}_LIBRARY)
+ if(NOT TARGET Matlab::${_matlab_library_target_name})
+ add_library(Matlab::${_matlab_library_target_name} UNKNOWN IMPORTED)
+ set_target_properties(Matlab::${_matlab_library_target_name} PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${Matlab_INCLUDE_DIRS}"
+ IMPORTED_LOCATION "${Matlab_${_matlab_library_variable_name}_LIBRARY}")
+ if(_matlab_library_target_name STREQUAL "mex" OR
+ _matlab_library_target_name STREQUAL "eng" OR
+ _matlab_library_target_name STREQUAL "mat")
+ set_target_properties(Matlab::${_matlab_library_target_name} PROPERTIES
+ INTERFACE_LINK_LIBRARIES Matlab::mx)
+ endif()
+ endif()
+ endif()
+endfunction()
+
+_Matlab_add_imported_target(MX mx)
+_Matlab_add_imported_target(MEX mex)
+_Matlab_add_imported_target(ENG eng)
+_Matlab_add_imported_target(MAT mat)
+_Matlab_add_imported_target(ENGINE MatlabEngine)
+_Matlab_add_imported_target(DATAARRAY MatlabDataArray)
+
find_package_handle_standard_args(
Matlab
FOUND_VAR Matlab_FOUND
diff --git a/Modules/FindPatch.cmake b/Modules/FindPatch.cmake
index 41086517d..f4fe4a614 100644
--- a/Modules/FindPatch.cmake
+++ b/Modules/FindPatch.cmake
@@ -43,7 +43,7 @@ endif()
# First search the PATH
find_program(Patch_EXECUTABLE
- NAME patch
+ NAMES patch
PATHS ${_patch_path}
DOC ${_doc}
)
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 01ad5ac6b..ef43a3ae9 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -12,11 +12,24 @@ Finds the ``pkg-config`` executable and adds the :command:`pkg_get_variable`,
following variables will also be set:
``PKG_CONFIG_FOUND``
- if pkg-config executable was found
-``PKG_CONFIG_EXECUTABLE``
- pathname of the pkg-config program
+ True if a pkg-config executable was found.
+
``PKG_CONFIG_VERSION_STRING``
- version of pkg-config (since CMake 2.8.8)
+ .. versionadded:: 2.8.8
+
+ The version of pkg-config that was found.
+
+``PKG_CONFIG_EXECUTABLE``
+ The pathname of the pkg-config program.
+
+``PKG_CONFIG_ARGN``
+ .. versionadded:: 3.22
+
+ A list of arguments to pass to pkg-config.
+
+Both ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN`` are initialized by the
+module, but may be overridden by the user. See `Variables Affecting Behavior`_
+for how these variables are initialized.
#]========================================]
@@ -29,13 +42,22 @@ set(PKG_CONFIG_VERSION 1)
# find pkg-config, use PKG_CONFIG if set
if((NOT PKG_CONFIG_EXECUTABLE) AND (NOT "$ENV{PKG_CONFIG}" STREQUAL ""))
- set(PKG_CONFIG_EXECUTABLE "$ENV{PKG_CONFIG}" CACHE FILEPATH "pkg-config executable")
+ separate_arguments(PKG_CONFIG_FROM_ENV_SPLIT NATIVE_COMMAND PROGRAM SEPARATE_ARGS "$ENV{PKG_CONFIG}")
+ list(LENGTH PKG_CONFIG_FROM_ENV_SPLIT PKG_CONFIG_FROM_ENV_SPLIT_ARGC)
+ if(PKG_CONFIG_FROM_ENV_SPLIT_ARGC GREATER 0)
+ list(GET PKG_CONFIG_FROM_ENV_SPLIT 0 PKG_CONFIG_FROM_ENV_ARGV0)
+ if(PKG_CONFIG_FROM_ENV_SPLIT_ARGC GREATER 1)
+ list(SUBLIST PKG_CONFIG_FROM_ENV_SPLIT 1 -1 PKG_CONFIG_ARGN)
+ endif()
+ set(PKG_CONFIG_EXECUTABLE "${PKG_CONFIG_FROM_ENV_ARGV0}" CACHE FILEPATH "pkg-config executable")
+ endif()
endif()
set(PKG_CONFIG_NAMES "pkg-config")
if(CMAKE_HOST_WIN32)
list(PREPEND PKG_CONFIG_NAMES "pkg-config.bat")
endif()
+list(PREPEND PKG_CONFIG_NAMES "pkgconf")
find_program(PKG_CONFIG_EXECUTABLE
NAMES ${PKG_CONFIG_NAMES}
@@ -43,9 +65,12 @@ find_program(PKG_CONFIG_EXECUTABLE
DOC "pkg-config executable")
mark_as_advanced(PKG_CONFIG_EXECUTABLE)
+set(PKG_CONFIG_ARGN "${PKG_CONFIG_ARGN}" CACHE STRING "Arguments to supply to pkg-config")
+mark_as_advanced(PKG_CONFIG_ARGN)
+
set(_PKG_CONFIG_FAILURE_MESSAGE "")
if (PKG_CONFIG_EXECUTABLE)
- execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --version
+ execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} --version
OUTPUT_VARIABLE PKG_CONFIG_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE _PKG_CONFIG_VERSION_ERROR ERROR_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _PKG_CONFIG_VERSION_RESULT
@@ -53,14 +78,18 @@ if (PKG_CONFIG_EXECUTABLE)
if (NOT _PKG_CONFIG_VERSION_RESULT EQUAL 0)
string(REPLACE "\n" "\n " _PKG_CONFIG_VERSION_ERROR " ${_PKG_CONFIG_VERSION_ERROR}")
+ if(PKG_CONFIG_ARGN)
+ string(REPLACE ";" " " PKG_CONFIG_ARGN " ${PKG_CONFIG_ARGN}")
+ endif()
string(APPEND _PKG_CONFIG_FAILURE_MESSAGE
"The command\n"
- " \"${PKG_CONFIG_EXECUTABLE}\" --version\n"
+ " \"${PKG_CONFIG_EXECUTABLE}\"${PKG_CONFIG_ARGN} --version\n"
" failed with output:\n${PKG_CONFIG_VERSION_STRING}\n"
" stderr: \n${_PKG_CONFIG_VERSION_ERROR}\n"
" result: \n${_PKG_CONFIG_VERSION_RESULT}"
)
set(PKG_CONFIG_EXECUTABLE "")
+ set(PKG_CONFIG_ARGN "")
unset(PKG_CONFIG_VERSION_STRING)
endif ()
unset(_PKG_CONFIG_VERSION_RESULT)
@@ -99,7 +128,7 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
set(_pkgconfig_invoke_result)
execute_process(
- COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist}
+ COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} ${ARGN} ${_pkglist}
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -393,6 +422,14 @@ macro(_pkg_set_path_internal)
unset(_lib_dirs)
unset(_pkgconfig_path)
endif()
+
+ # Tell pkg-config not to strip any -L paths so we can search them all.
+ if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS})
+ set(_pkgconfig_allow_system_libs_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS}")
+ else()
+ unset(_pkgconfig_allow_system_libs_old)
+ endif()
+ set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 0)
endmacro()
macro(_pkg_restore_path_internal)
@@ -400,6 +437,10 @@ macro(_pkg_restore_path_internal)
# Restore the environment variable
set(ENV{PKG_CONFIG_PATH} "${_pkgconfig_path_old}")
endif()
+ if(DEFINED _pkgconfig_allow_system_libs_old)
+ set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}")
+ unset(_pkgconfig_allow_system_libs_old)
+ endif()
unset(_extra_paths)
unset(_pkgconfig_path_old)
@@ -541,7 +582,7 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma
# execute the query
execute_process(
- COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query}
+ COMMAND ${PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_ARGN} ${_pkg_check_modules_exist_query}
RESULT_VARIABLE _pkgconfig_retval
ERROR_VARIABLE _pkgconfig_error
ERROR_STRIP_TRAILING_WHITESPACE)
@@ -893,12 +934,30 @@ Variables Affecting Behavior
.. variable:: PKG_CONFIG_EXECUTABLE
- This can be set to the path of the pkg-config executable. If not provided,
- it will be set by the module as a result of calling :command:`find_program`
- internally.
+ This cache variable can be set to the path of the pkg-config executable.
+ :command:`find_program` is called internally by the module with this
+ variable.
.. versionadded:: 3.1
- The ``PKG_CONFIG`` environment variable can be used as a hint.
+ The ``PKG_CONFIG`` environment variable can be used as a hint if
+ ``PKG_CONFIG_EXECUTABLE`` has not yet been set.
+
+ .. versionchanged:: 3.22
+ If the ``PKG_CONFIG`` environment variable is set, only the first
+ argument is taken from it when using it as a hint.
+
+.. variable:: PKG_CONFIG_ARGN
+
+ .. versionadded:: 3.22
+
+ This cache variable can be set to a list of arguments to additionally pass
+ to pkg-config if needed. If not provided, it will be initialized from the
+ ``PKG_CONFIG`` environment variable, if set. The first argument in that
+ environment variable is assumed to be the pkg-config program, while all
+ remaining arguments after that are used to initialize ``PKG_CONFIG_ARGN``.
+ If no such environment variable is defined, ``PKG_CONFIG_ARGN`` is
+ initialized to an empty string. The module does not update the variable once
+ it has been set in the cache.
.. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index c6a3451f7..e4d6cf3cb 100644
--- a/Modules/FindThreads.cmake
+++ b/Modules/FindThreads.cmake
@@ -106,7 +106,7 @@ endmacro()
# Do NOT even think about using it outside of this file!
macro(_check_pthreads_flag)
if(NOT Threads_FOUND)
- # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread
+ # If we did not find -lpthreads, -lpthread, or -lthread, look for -pthread
if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG)
message(CHECK_START "Check if compiler accepts -pthread")
if(CMAKE_C_COMPILER_LOADED)
diff --git a/Modules/FindX11.cmake b/Modules/FindX11.cmake
index d480fc480..fd5ee5395 100644
--- a/Modules/FindX11.cmake
+++ b/Modules/FindX11.cmake
@@ -828,6 +828,12 @@ if (UNIX)
X11_Xau_INCLUDE_PATH
X11_xcb_LIB
X11_xcb_INCLUDE_PATH
+ X11_xcb_icccm_LIB
+ X11_xcb_icccm_INCLUDE_PATH
+ X11_xcb_util_LIB
+ X11_xcb_util_INCLUDE_PATH
+ X11_xcb_xfixes_LIB
+ X11_xcb_xfixes_INCLUDE_PATH
X11_xcb_xkb_LIB
X11_X11_xcb_LIB
X11_X11_xcb_INCLUDE_PATH
diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake
index 4aaad797b..6ca424ad5 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -218,6 +218,7 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
+ # - we are NOT building for conda
# - we are on a 64 bits system
# reason is: amd64 ABI: https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
@@ -239,11 +240,34 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
endif()
+
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$"
- AND NOT CMAKE_CROSSCOMPILING
- AND NOT EXISTS "/etc/alpine-release"
- AND NOT EXISTS "/etc/arch-release")
- if (EXISTS "/etc/debian_version") # is this a debian system ?
+ AND NOT CMAKE_CROSSCOMPILING)
+ unset(__system_type_for_install)
+ if(DEFINED ENV{CONDA_BUILD} AND DEFINED ENV{PREFIX})
+ set(conda_prefix "$ENV{PREFIX}")
+ cmake_path(ABSOLUTE_PATH conda_prefix NORMALIZE)
+ if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix)
+ set(__system_type_for_install "conda")
+ endif()
+ elseif(DEFINED ENV{CONDA_PREFIX})
+ set(conda_prefix "$ENV{CONDA_PREFIX}")
+ cmake_path(ABSOLUTE_PATH conda_prefix NORMALIZE)
+ if("${CMAKE_INSTALL_PREFIX}" STREQUAL conda_prefix)
+ set(__system_type_for_install "conda")
+ endif()
+ endif()
+ if(NOT __system_type_for_install)
+ if (EXISTS "/etc/alpine-release")
+ set(__system_type_for_install "alpine")
+ elseif (EXISTS "/etc/arch-release")
+ set(__system_type_for_install "arch linux")
+ elseif (EXISTS "/etc/debian_version")
+ set(__system_type_for_install "debian")
+ endif()
+ endif()
+
+ if(__system_type_for_install STREQUAL "debian")
if(CMAKE_LIBRARY_ARCHITECTURE)
if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/?$")
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
@@ -253,7 +277,8 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
set(__LAST_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
endif()
- else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
+ elseif(NOT DEFINED __system_type_for_install)
+ # not debian, alpine, arch, or conda so rely on CMAKE_SIZEOF_VOID_P:
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
if(DEFINED _GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX)
@@ -262,6 +287,8 @@ if(NOT DEFINED CMAKE_INSTALL_LIBDIR OR (_libdir_set
endif()
endif()
endif()
+ unset(__system_type_for_install)
+
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "Object code libraries (${_LIBDIR_DEFAULT})")
elseif(DEFINED __LAST_LIBDIR_DEFAULT
diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake
index e90a9b5b7..53584c639 100644
--- a/Modules/GetPrerequisites.cmake
+++ b/Modules/GetPrerequisites.cmake
@@ -746,7 +746,7 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
set(gp_regex_error "")
set(gp_regex_fallback "")
set(gp_regex_cmp_count 1)
- elseif(gp_tool MATCHES "objdump$")
+ elseif(gp_tool MATCHES "objdump(\\.exe)?$")
set(gp_cmd_args "-p")
set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$")
set(gp_regex_error "")
diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 80d8e2397..f5f4f0238 100644
--- a/Modules/GoogleTest.cmake
+++ b/Modules/GoogleTest.cmake
@@ -151,6 +151,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
[WORKING_DIRECTORY dir]
[TEST_PREFIX prefix]
[TEST_SUFFIX suffix]
+ [TEST_FILTER expr]
[NO_PRETTY_TYPES] [NO_PRETTY_VALUES]
[PROPERTIES name1 value1...]
[TEST_LIST var]
@@ -204,6 +205,15 @@ same as the Google Test name (i.e. ``suite.testcase``); see also
every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may
be specified.
+ ``TEST_FILTER expr``
+ .. versionadded:: 3.22
+
+ Filter expression to pass as a ``--gtest_filter`` argument during test
+ discovery. Note that the expression is a wildcard-based format that
+ matches against the original test names as used by gtest. For type or
+ value-parameterized tests, these names may be different to the potentially
+ pretty-printed test names that ``ctest`` uses.
+
``NO_PRETTY_TYPES``
By default, the type index of type-parameterized tests is replaced by the
actual type name in the CTest test name. If this behavior is undesirable
@@ -411,7 +421,7 @@ function(gtest_discover_tests TARGET)
""
"NO_PRETTY_TYPES;NO_PRETTY_VALUES"
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT;XML_OUTPUT_DIR;DISCOVERY_MODE"
- "EXTRA_ARGS;PROPERTIES"
+ "EXTRA_ARGS;PROPERTIES;TEST_FILTER"
${ARGN}
)
@@ -475,6 +485,7 @@ function(gtest_discover_tests TARGET)
-D "TEST_PROPERTIES=${_PROPERTIES}"
-D "TEST_PREFIX=${_TEST_PREFIX}"
-D "TEST_SUFFIX=${_TEST_SUFFIX}"
+ -D "TEST_FILTER=${_TEST_FILTER}"
-D "NO_PRETTY_TYPES=${_NO_PRETTY_TYPES}"
-D "NO_PRETTY_VALUES=${_NO_PRETTY_VALUES}"
-D "TEST_LIST=${_TEST_LIST}"
@@ -505,7 +516,8 @@ function(gtest_discover_tests TARGET)
string(CONCAT ctest_include_content
"if(EXISTS \"$<TARGET_FILE:${TARGET}>\")" "\n"
" if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n"
- " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\")" "\n"
+ " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\" OR\n"
+ " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n"
" include(\"${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}\")" "\n"
" gtest_discover_tests_impl(" "\n"
" TEST_EXECUTABLE" " [==[" "$<TARGET_FILE:${TARGET}>" "]==]" "\n"
@@ -515,6 +527,7 @@ function(gtest_discover_tests TARGET)
" TEST_PROPERTIES" " [==[" "${_PROPERTIES}" "]==]" "\n"
" TEST_PREFIX" " [==[" "${_TEST_PREFIX}" "]==]" "\n"
" TEST_SUFFIX" " [==[" "${_TEST_SUFFIX}" "]==]" "\n"
+ " TEST_FILTER" " [==[" "${_TEST_FILTER}" "]==]" "\n"
" NO_PRETTY_TYPES" " [==[" "${_NO_PRETTY_TYPES}" "]==]" "\n"
" NO_PRETTY_VALUES" " [==[" "${_NO_PRETTY_VALUES}" "]==]" "\n"
" TEST_LIST" " [==[" "${_TEST_LIST}" "]==]" "\n"
diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake
index 0f79c9afc..6b3bf34ee 100644
--- a/Modules/GoogleTestAddTests.cmake
+++ b/Modules/GoogleTestAddTests.cmake
@@ -44,7 +44,7 @@ function(gtest_discover_tests_impl)
cmake_parse_arguments(
""
""
- "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR"
+ "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR;TEST_FILTER"
"TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR"
${ARGN}
)
@@ -58,6 +58,12 @@ function(gtest_discover_tests_impl)
set(tests)
set(tests_buffer)
+ if(_TEST_FILTER)
+ set(filter "--gtest_filter=${_TEST_FILTER}")
+ else()
+ set(filter)
+ endif()
+
# Run test executable to get list of available tests
if(NOT EXISTS "${_TEST_EXECUTABLE}")
message(FATAL_ERROR
@@ -66,7 +72,7 @@ function(gtest_discover_tests_impl)
)
endif()
execute_process(
- COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests
+ COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests ${filter}
WORKING_DIRECTORY "${_TEST_WORKING_DIR}"
TIMEOUT ${_TEST_DISCOVERY_TIMEOUT}
OUTPUT_VARIABLE output
@@ -178,6 +184,7 @@ if(CMAKE_SCRIPT_MODE_FILE)
TEST_WORKING_DIR ${TEST_WORKING_DIR}
TEST_PREFIX ${TEST_PREFIX}
TEST_SUFFIX ${TEST_SUFFIX}
+ TEST_FILTER ${TEST_FILTER}
TEST_LIST ${TEST_LIST}
CTEST_FILE ${CTEST_FILE}
TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT}
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index a2672784d..689cab591 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -73,6 +73,8 @@ set(_IRSL_HAVE_MSVC FALSE)
foreach(LANG IN ITEMS C CXX Fortran)
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "Intel")
if(NOT _IRSL_HAVE_Intel)
+ # The oneAPI icx/ifx compilers are under ${os}/bin.
+ # The classic icc/icpc/icl/ifort compilers may be under ${os}/bin/intel64.
get_filename_component(_Intel_basedir "${CMAKE_${LANG}_COMPILER}" PATH)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_Intel_archdir intel64)
@@ -80,19 +82,36 @@ foreach(LANG IN ITEMS C CXX Fortran)
set(_Intel_archdir ia32)
endif()
set(_Intel_compiler_ver ${CMAKE_${LANG}_COMPILER_VERSION})
- if(WIN32 AND EXISTS "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler")
- get_filename_component(_Intel_redistdir "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler" ABSOLUTE)
- elseif(WIN32)
- get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler" ABSOLUTE)
+ if(WIN32)
+ set(_Intel_possible_redistdirs
+ "${_Intel_basedir}/../redist/${_Intel_archdir}_win/compiler"
+ "${_Intel_basedir}/../redist/${_Intel_archdir}/compiler"
+ "${_Intel_basedir}/../../redist/${_Intel_archdir}_win/compiler"
+ "${_Intel_basedir}/../../redist/${_Intel_archdir}/compiler"
+ )
elseif(APPLE)
- get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib" ABSOLUTE)
+ set(_Intel_possible_redistdirs
+ "${_Intel_basedir}/../../compiler/lib"
+ )
else()
- if(EXISTS "${_Intel_basedir}/../lib/${_Intel_archdir}_lin")
- get_filename_component(_Intel_redistdir "${_Intel_basedir}/../lib/${_Intel_archdir}" ABSOLUTE)
- else()
- get_filename_component(_Intel_redistdir "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin" ABSOLUTE)
+ set(_Intel_possible_redistdirs
+ "${_Intel_basedir}/../lib/${_Intel_archdir}"
+ "${_Intel_basedir}/../../compiler/lib/${_Intel_archdir}_lin"
+ )
+ endif()
+
+ set(_Intel_redistdir NOT-FOUND)
+ foreach(dir IN LISTS _Intel_possible_redistdirs)
+ if(EXISTS "${dir}")
+ set(_Intel_redistdir "${dir}")
+ break()
endif()
+ endforeach()
+ # Fall back to last dir
+ if(NOT _Intel_redistdir)
+ list(POP_BACK _Intel_possible_redistdirs _Intel_redistdir)
endif()
+ unset(_Intel_possible_redistdirs)
set(_IRSL_HAVE_Intel TRUE)
endif()
elseif("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "MSVC")
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 967ad7bc1..c115f003e 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -662,10 +662,12 @@ function(cpack_deb_prepare_package_vars)
# add ldconfig call in default postrm and postint
set(CPACK_ADD_LDCONFIG_CALL 0)
+ # all files in CPACK_DEB_SHARED_OBJECT_FILES have dot at the beginning
+ set(_LDCONF_DEFAULTS "./lib" "./usr/lib")
foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
get_filename_component(_DIR ${_FILE} DIRECTORY)
- # all files in CPACK_DEB_SHARED_OBJECT_FILES have dot at the beginning
- if(_DIR STREQUAL "./lib" OR _DIR STREQUAL "./usr/lib")
+ get_filename_component(_PARENT_DIR ${_DIR} DIRECTORY)
+ if(_DIR IN_LIST _LDCONF_DEFAULTS OR _PARENT_DIR IN_LIST _LDCONF_DEFAULTS)
set(CPACK_ADD_LDCONFIG_CALL 1)
endif()
endforeach()
diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake
index cbd748b2c..c72bf6db4 100644
--- a/Modules/Internal/CPack/CPackRPM.cmake
+++ b/Modules/Internal/CPack/CPackRPM.cmake
@@ -1160,6 +1160,16 @@ function(cpack_rpm_generate_package)
set(TMP_RPM_SPEC_INSTALL_POST "%define __spec_install_post ${CPACK_RPM_SPEC_INSTALL_POST}")
endif()
+ # CPACK_RPM_REQUIRES_EXCLUDE_FROM
+ # May be defined to keep the dependency generator from
+ # scanning specific files or directories for deps.
+ if(CPACK_RPM_REQUIRES_EXCLUDE_FROM)
+ if(CPACK_RPM_PACKAGE_DEBUG)
+ message("CPackRPM:Debug: User defined CPACK_RPM_REQUIRES_EXCLUDE_FROM = ${CPACK_RPM_REQUIRES_EXCLUDE_FROM}")
+ endif()
+ set(TMP_RPM_REQUIRES_EXCLUDE_FROM "%global __requires_exclude_from ${CPACK_RPM_REQUIRES_EXCLUDE_FROM}")
+ endif()
+
# CPACK_RPM_POST_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE)
# CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE)
# CPACK_RPM_POST_TRANS_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_TRANS_SCRIPT_FILE)
@@ -1648,6 +1658,7 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
\@FILE_NAME_DEFINE\@
%define _unpackaged_files_terminate_build 0
\@TMP_RPM_SPEC_INSTALL_POST\@
+\@TMP_RPM_REQUIRES_EXCLUDE_FROM\@
\@CPACK_RPM_SPEC_MORE_DEFINE\@
\@CPACK_RPM_COMPRESSION_TYPE_TMP\@
@@ -1782,6 +1793,7 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
\@FILE_NAME_DEFINE\@
%define _unpackaged_files_terminate_build 0
\@TMP_RPM_SPEC_INSTALL_POST\@
+\@TMP_RPM_REQUIRES_EXCLUDE_FROM\@
\@CPACK_RPM_SPEC_MORE_DEFINE\@
\@CPACK_RPM_COMPRESSION_TYPE_TMP\@
diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in
index 0a9c4877d..8a0c9726c 100644
--- a/Modules/Internal/CPack/NSIS.template.in
+++ b/Modules/Internal/CPack/NSIS.template.in
@@ -540,7 +540,7 @@ FunctionEnd
@CPACK_NSIS_INSTALLER_WELCOME_TITLE_3LINES_CODE@
!insertmacro MUI_PAGE_WELCOME
- !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
+ @CPACK_NSIS_LICENSE_PAGE@
Page custom InstallOptionsPage
!insertmacro MUI_PAGE_DIRECTORY
@@ -564,21 +564,27 @@ FunctionEnd
;Languages
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
+ !insertmacro MUI_LANGUAGE "Afrikaans"
!insertmacro MUI_LANGUAGE "Albanian"
!insertmacro MUI_LANGUAGE "Arabic"
+ !insertmacro MUI_LANGUAGE "Asturian"
!insertmacro MUI_LANGUAGE "Basque"
!insertmacro MUI_LANGUAGE "Belarusian"
!insertmacro MUI_LANGUAGE "Bosnian"
!insertmacro MUI_LANGUAGE "Breton"
!insertmacro MUI_LANGUAGE "Bulgarian"
+ !insertmacro MUI_LANGUAGE "Catalan"
+ !insertmacro MUI_LANGUAGE "Corsican"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Czech"
!insertmacro MUI_LANGUAGE "Danish"
!insertmacro MUI_LANGUAGE "Dutch"
+ !insertmacro MUI_LANGUAGE "Esperanto"
!insertmacro MUI_LANGUAGE "Estonian"
!insertmacro MUI_LANGUAGE "Farsi"
!insertmacro MUI_LANGUAGE "Finnish"
!insertmacro MUI_LANGUAGE "French"
+ !insertmacro MUI_LANGUAGE "Galician"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Greek"
!insertmacro MUI_LANGUAGE "Hebrew"
@@ -597,22 +603,29 @@ FunctionEnd
!insertmacro MUI_LANGUAGE "Malay"
!insertmacro MUI_LANGUAGE "Mongolian"
!insertmacro MUI_LANGUAGE "Norwegian"
+ !insertmacro MUI_LANGUAGE "NorwegianNynorsk"
+ !insertmacro MUI_LANGUAGE "Pashto"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "PortugueseBR"
!insertmacro MUI_LANGUAGE "Romanian"
!insertmacro MUI_LANGUAGE "Russian"
+ !insertmacro MUI_LANGUAGE "ScotsGaelic"
!insertmacro MUI_LANGUAGE "Serbian"
!insertmacro MUI_LANGUAGE "SerbianLatin"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "Slovak"
!insertmacro MUI_LANGUAGE "Slovenian"
!insertmacro MUI_LANGUAGE "Spanish"
+ !insertmacro MUI_LANGUAGE "SpanishInternational"
!insertmacro MUI_LANGUAGE "Swedish"
+ !insertmacro MUI_LANGUAGE "Tatar"
!insertmacro MUI_LANGUAGE "Thai"
!insertmacro MUI_LANGUAGE "TradChinese"
!insertmacro MUI_LANGUAGE "Turkish"
!insertmacro MUI_LANGUAGE "Ukrainian"
+ !insertmacro MUI_LANGUAGE "Uzbek"
+ !insertmacro MUI_LANGUAGE "Vietnamese"
!insertmacro MUI_LANGUAGE "Welsh"
;--------------------------------
@@ -661,7 +674,7 @@ Section "-Core installation"
Push "@CPACK_PACKAGE_VENDOR@"
Call ConditionalAddToRegisty
Push "UninstallString"
- Push "$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe"
+ Push "$\"$INSTDIR\@CPACK_NSIS_UNINSTALL_NAME@.exe$\""
Call ConditionalAddToRegisty
Push "NoRepair"
Push "1"
diff --git a/Modules/Internal/OSRelease/010-TryOldCentOS.cmake b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake
new file mode 100644
index 000000000..ff358977f
--- /dev/null
+++ b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake
@@ -0,0 +1,41 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# Author: Alex Turbov
+
+if(NOT EXISTS "${CMAKE_SYSROOT}/etc/centos-release")
+ return()
+endif()
+
+# Get the first string only
+file(
+ STRINGS "${CMAKE_SYSROOT}/etc/centos-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+
+#
+# Example:
+# CentOS release 6.10 (Final)
+#
+if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "CentOS release ([0-9\.]+) .*")
+
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME CentOS)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}")
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID centos)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE rhel)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1})
+
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+
+endif()
+
+unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
diff --git a/Modules/Internal/OSRelease/020-TryDebianVersion.cmake b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake
new file mode 100644
index 000000000..8ebe19a72
--- /dev/null
+++ b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake
@@ -0,0 +1,38 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+# Author: Alex Turbov
+
+if(NOT EXISTS "${CMAKE_SYSROOT}/etc/debian_version")
+ return()
+endif()
+
+# Get the first string only
+file(
+ STRINGS "${CMAKE_SYSROOT}/etc/debian_version" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ LIMIT_COUNT 1
+ )
+
+#
+# Example:
+# 6.0.10 # Old debian
+# wheezy/sid # Ubuntu
+#
+if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "[0-9]+(\.[0-9]+)*")
+
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Debian)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID debian)
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT})
+ set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT})
+
+ list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
+
+endif()
+
+unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT)
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index 7b67f839e..a4e957495 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -52,14 +52,16 @@ if(CMAKE_GENERATOR MATCHES "Visual Studio")
endif()
configure_file(${CMAKE_ROOT}/Modules/Platform/Android/VCXProjInspect.vcxproj.in
${CMAKE_PLATFORM_INFO_DIR}/VCXProjInspect.vcxproj @ONLY)
+ cmake_host_system_information(RESULT _msbuild QUERY VS_MSBUILD_COMMAND) # undocumented query
execute_process(
- COMMAND "${CMAKE_VS_MSBUILD_COMMAND}" "VCXProjInspect.vcxproj"
+ COMMAND "${_msbuild}" "VCXProjInspect.vcxproj"
"/p:Configuration=Debug" "/p:Platform=${vcx_platform}"
WORKING_DIRECTORY ${CMAKE_PLATFORM_INFO_DIR}
OUTPUT_VARIABLE VCXPROJ_INSPECT_OUTPUT
ERROR_VARIABLE VCXPROJ_INSPECT_OUTPUT
RESULT_VARIABLE VCXPROJ_INSPECT_RESULT
)
+ unset(_msbuild)
if(NOT CMAKE_SYSROOT AND VCXPROJ_INSPECT_OUTPUT MATCHES "CMAKE_SYSROOT=([^%\r\n]+)[\r\n]")
# Strip VS diagnostic output from the end of the line.
string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _sysroot "${CMAKE_MATCH_1}")
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index 373be760d..1c32018f3 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -38,6 +38,8 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ")
set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP)
+ set(CMAKE_${lang}_LINKER_MANIFEST_FLAG " -Xlinker /MANIFESTINPUT:")
+
if("${CMAKE_${lang}_SIMULATE_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)")
math(EXPR MSVC_VERSION "${CMAKE_MATCH_1}*100 + ${CMAKE_MATCH_2}")
endif()
@@ -66,10 +68,10 @@ macro(__windows_compiler_clang_gnu lang)
set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES>")
+ "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>")
set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY})
set(CMAKE_${lang}_LINK_EXECUTABLE
- "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")
+ "<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>")
set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows")
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console")
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index a04882f56..51dc14631 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -8,6 +8,8 @@ if(__WINDOWS_GNU)
endif()
set(__WINDOWS_GNU 1)
+set(MINGW 1)
+
set(CMAKE_IMPORT_LIBRARY_PREFIX "lib")
set(CMAKE_SHARED_LIBRARY_PREFIX "lib")
set(CMAKE_SHARED_MODULE_PREFIX "lib")
@@ -19,16 +21,12 @@ set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
set(CMAKE_SHARED_MODULE_SUFFIX ".dll")
set(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
-if(MSYS OR MINGW)
- set(CMAKE_EXTRA_LINK_EXTENSIONS ".lib") # MinGW can also link to a MS .lib
-endif()
+set(CMAKE_EXTRA_LINK_EXTENSIONS ".lib") # MinGW can also link to a MS .lib
-if(MINGW)
- set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
- set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib")
- set(CMAKE_C_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32")
- set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
-endif()
+set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
+set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib")
+set(CMAKE_C_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32")
+set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
set(CMAKE_DL_LIBS "")
set(CMAKE_LIBRARY_PATH_FLAG "-L")
@@ -48,21 +46,19 @@ endif()
macro(__windows_compiler_gnu lang)
- if(MSYS OR MINGW)
- # Create archiving rules to support large object file lists for static libraries.
- set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
-
- # Initialize C link type selection flags. These flags are used when
- # building a shared library, shared module, or executable that links
- # to other libraries to select whether to use the static or shared
- # versions of the libraries.
- foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
- set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic")
- set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
- endforeach()
- endif()
+ # Create archiving rules to support large object file lists for static libraries.
+ set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+
+ # Initialize C link type selection flags. These flags are used when
+ # building a shared library, shared module, or executable that links
+ # to other libraries to select whether to use the static or shared
+ # versions of the libraries.
+ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
+ set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic")
+ set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
+ endforeach()
# No -fPIC on Windows
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "")
diff --git a/Modules/Platform/Windows-Intel-C.cmake b/Modules/Platform/Windows-Intel-C.cmake
index e4d9b93ee..152b27c30 100644
--- a/Modules/Platform/Windows-Intel-C.cmake
+++ b/Modules/Platform/Windows-Intel-C.cmake
@@ -1,7 +1,7 @@
include(Platform/Windows-Intel)
__windows_compiler_intel(C)
-set(CMAKE_DEPFILE_FLAGS_C "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+set(CMAKE_DEPFILE_FLAGS_C "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
set(CMAKE_C_DEPFILE_FORMAT gcc)
if(CMAKE_GENERATOR MATCHES "^Ninja")
diff --git a/Modules/Platform/Windows-Intel-CXX.cmake b/Modules/Platform/Windows-Intel-CXX.cmake
index 6adbb6e19..ce33ae186 100644
--- a/Modules/Platform/Windows-Intel-CXX.cmake
+++ b/Modules/Platform/Windows-Intel-CXX.cmake
@@ -2,7 +2,7 @@ include(Platform/Windows-Intel)
set(_COMPILE_CXX " /TP")
__windows_compiler_intel(CXX)
-set(CMAKE_DEPFILE_FLAGS_CXX "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+set(CMAKE_DEPFILE_FLAGS_CXX "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
if(CMAKE_GENERATOR MATCHES "^Ninja")
diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake
index 8231e784b..b9ea03799 100644
--- a/Modules/Platform/Windows-IntelLLVM.cmake
+++ b/Modules/Platform/Windows-IntelLLVM.cmake
@@ -12,6 +12,6 @@ include(Platform/Windows-MSVC)
macro(__windows_compiler_intel lang)
__windows_compiler_msvc(${lang})
- set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
set(CMAKE_${lang}_DEPFILE_FORMAT gcc)
endmacro()
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index b48c33ce3..9808861cd 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -192,12 +192,17 @@ ensure generated files will receive the required settings.
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
itself. This property is only meaningful for
:ref:`Makefile <Makefile Generators>`,
- :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default
- value is ``FALSE``.
+ :ref:`Ninja <Ninja Generators>`, :generator:`Xcode`, and
+ :ref:`Visual Studio <Visual Studio Generators>`
+ (:generator:`Visual Studio 11 2012` and above) generators. Default value is
+ ``FALSE``.
.. versionadded:: 3.21
Added the support of :generator:`Xcode` generator.
+ .. versionadded:: 3.22
+ Added the support of :ref:`Visual Studio Generators`.
+
``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language.
This is required if it cannot be scanned automatically from source
@@ -342,8 +347,10 @@ as well as ``SWIG``:
If set to ``TRUE``, implicit dependencies are generated by the ``swig`` tool
itself. This variable is only meaningful for
:ref:`Makefile <Makefile Generators>`,
- :ref:`Ninja <Ninja Generators>` and :generator:`Xcode` generators. Default
- value is ``FALSE``.
+ :ref:`Ninja <Ninja Generators>`, :generator:`Xcode`, and
+ :ref:`Visual Studio <Visual Studio Generators>`
+ (:generator:`Visual Studio 11 2012` and above) generators. Default value is
+ ``FALSE``.
Source file property ``USE_SWIG_DEPENDENCIES``, if not defined, will be
initialized with the value of this variable.
@@ -351,6 +358,9 @@ as well as ``SWIG``:
.. versionadded:: 3.21
Added the support of :generator:`Xcode` generator.
+ .. versionadded:: 3.22
+ Added the support of :ref:`Visual Studio Generators`.
+
#]=======================================================================]
cmake_policy(PUSH)
@@ -515,7 +525,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
endif()
set (use_swig_dependencies ${SWIG_USE_SWIG_DEPENDENCIES})
- if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])")
get_property(use_swig_dependencies_set SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES SET)
if (use_swig_dependencies_set)
get_property(use_swig_dependencies SOURCE "${infile}" PROPERTY USE_SWIG_DEPENDENCIES)
@@ -676,7 +686,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
${swig_custom_products}
${swig_cleanup_command}
# Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
- COMMAND "${CMAKE_COMMAND}" -E make_directory "${workingdir}" "${outdir}" "${outfiledir}"
+ COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
${swig_timestamp_command}
COMMAND "${CMAKE_COMMAND}" -E env "SWIG_LIB=${SWIG_DIR}" "${SWIG_EXECUTABLE}"
"-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
@@ -840,8 +850,9 @@ function(SWIG_ADD_LIBRARY name)
set(SWIG_SOURCE_FILE_EXTENSIONS ".i")
endif()
- if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
- # For Makefiles and Ninja generators, use SWIG generated dependencies
+ if (CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])")
+ # For Makefiles, Ninja, Xcode and Visual Studio generators,
+ # use SWIG generated dependencies if requested
if (NOT DEFINED SWIG_USE_SWIG_DEPENDENCIES)
set (SWIG_USE_SWIG_DEPENDENCIES OFF)
endif()
diff --git a/Modules/VTKCompatibility.cmake b/Modules/VTKCompatibility.cmake
index 1b0815e85..4ee7643c2 100644
--- a/Modules/VTKCompatibility.cmake
+++ b/Modules/VTKCompatibility.cmake
@@ -1,6 +1,10 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
+# Not needed for "modern" VTK.
+if (EXISTS "${VTK_SOURCE_DIR}/CMake/vtkModule.cmake")
+ return ()
+endif ()
if(APPLE)
set(CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 9a18184fd..c8498a991 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -10,36 +10,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX")
endif()
include(CheckIncludeFile)
-# Check if we can build support for ELF parsing.
-if(WIN32)
- set(HAVE_ELF_H 0)
-elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
- CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H)
-else()
- CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
-endif()
-if(HAVE_ELF_H)
- set(CMake_USE_ELF_PARSER 1)
-elseif(HAIKU)
- # On Haiku, we need to include elf32.h from the private headers
- set(CMake_HAIKU_INCLUDE_DIRS
- /boot/system/develop/headers/private/system
- /boot/system/develop/headers/private/system/arch/x86
- )
-
- set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS})
- CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H)
- unset(CMAKE_REQUIRED_INCLUDES)
-
- if(HAVE_ELF32_H)
- set(CMake_USE_ELF_PARSER 1)
- else()
- unset(CMake_HAIKU_INCLUDE_DIRS)
- set(CMake_USE_ELF_PARSER)
- endif()
-else()
- set(CMake_USE_ELF_PARSER)
-endif()
if(NOT CMake_DEFAULT_RECURSION_LIMIT)
if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST})
@@ -111,11 +81,6 @@ include_directories(
${CMake_HAIKU_INCLUDE_DIRS}
)
-# Check if we can build the ELF parser.
-if(CMake_USE_ELF_PARSER)
- set(ELF_SRCS cmELF.h cmELF.cxx)
-endif()
-
# Check if we can build the Mach-O parser.
if(CMake_USE_MACH_PARSER)
set(MACH_SRCS cmMachO.h cmMachO.cxx)
@@ -245,7 +210,8 @@ set(SRCS
cmDocumentationSection.cxx
cmDynamicLoader.cxx
cmDynamicLoader.h
- ${ELF_SRCS}
+ cmELF.h
+ cmELF.cxx
cmExprParserHelper.cxx
cmExportBuildAndroidMKGenerator.h
cmExportBuildAndroidMKGenerator.cxx
@@ -415,6 +381,8 @@ set(SRCS
cmProcessOutput.h
cmProcessTools.cxx
cmProcessTools.h
+ cmValue.cxx
+ cmValue.h
cmProperty.h
cmPropertyDefinition.cxx
cmPropertyDefinition.h
@@ -834,7 +802,7 @@ if (WIN32)
endif ()
# Watcom support
-if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
+if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE)
list(APPEND SRCS
cmGlobalWatcomWMakeGenerator.cxx
@@ -994,6 +962,7 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestSubmitHandler.cxx
CTest/cmCTestTestCommand.cxx
CTest/cmCTestTestHandler.cxx
+ CTest/cmCTestTestMeasurementXMLParser.cxx
CTest/cmCTestUpdateCommand.cxx
CTest/cmCTestUpdateHandler.cxx
CTest/cmCTestUploadCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 392f8a9c9..512f47eda 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
-set(CMake_VERSION_MINOR 21)
-set(CMake_VERSION_PATCH 7)
+set(CMake_VERSION_MINOR 22)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
@@ -21,7 +21,7 @@ endif()
if(NOT CMake_VERSION_NO_GIT)
# If this source was exported by 'git archive', use its commit info.
- set(git_info [==[97073b1991 CMake 3.21.7]==])
+ set(git_info [==[ff8c3acc0f CMake 3.22.0]==])
# Otherwise, try to identify the current development source version.
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
index 87ebbfeb9..f6b8a8a53 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.cxx
+++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx
@@ -21,7 +21,7 @@ cmCPackIFWCommon::cmCPackIFWCommon()
{
}
-const char* cmCPackIFWCommon::GetOption(const std::string& op) const
+cmValue cmCPackIFWCommon::GetOption(const std::string& op) const
{
return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op)
: nullptr;
@@ -51,7 +51,7 @@ bool cmCPackIFWCommon::IsVersionLess(const char* version) const
}
return cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->Generator->FrameworkVersion.data(), version);
+ cmSystemTools::OP_LESS, this->Generator->FrameworkVersion, version);
}
bool cmCPackIFWCommon::IsVersionGreater(const char* version) const
@@ -61,8 +61,7 @@ bool cmCPackIFWCommon::IsVersionGreater(const char* version) const
}
return cmSystemTools::VersionCompare(
- cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion.data(),
- version);
+ cmSystemTools::OP_GREATER, this->Generator->FrameworkVersion, version);
}
bool cmCPackIFWCommon::IsVersionEqual(const char* version) const
@@ -72,8 +71,7 @@ bool cmCPackIFWCommon::IsVersionEqual(const char* version) const
}
return cmSystemTools::VersionCompare(
- cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion.data(),
- version);
+ cmSystemTools::OP_EQUAL, this->Generator->FrameworkVersion, version);
}
void cmCPackIFWCommon::ExpandListArgument(
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h
index 42deda4ea..f2e6b889c 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.h
+++ b/Source/CPack/IFW/cmCPackIFWCommon.h
@@ -7,6 +7,8 @@
#include <map>
#include <string>
+#include "cmValue.h"
+
class cmCPackIFWGenerator;
class cmXMLWriter;
@@ -26,7 +28,7 @@ public:
public:
// Internal implementation
- const char* GetOption(const std::string& op) const;
+ cmValue GetOption(const std::string& op) const;
bool IsOn(const std::string& op) const;
bool IsSetToOff(const std::string& op) const;
bool IsSetToEmpty(const std::string& op) const;
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 2806c614e..b375ba605 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackIFWGenerator::cmCPackIFWGenerator()
{
@@ -248,9 +249,9 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix()
tmpPref += "packages/" + this->GetRootPackageName() + "/data";
}
- this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str());
+ this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref);
- return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX");
+ return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX")->c_str();
}
const char* cmCPackIFWGenerator::GetOutputExtension()
@@ -273,11 +274,11 @@ int cmCPackIFWGenerator::InitializeInternal()
// Look 'binarycreator' executable (needs)
- const char* BinCreatorStr = this->GetOption(BinCreatorOpt);
+ cmValue BinCreatorStr = this->GetOption(BinCreatorOpt);
if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) {
this->BinCreator.clear();
} else {
- this->BinCreator = BinCreatorStr;
+ this->BinCreator = *BinCreatorStr;
}
if (this->BinCreator.empty()) {
@@ -290,16 +291,16 @@ int cmCPackIFWGenerator::InitializeInternal()
// Look 'repogen' executable (optional)
- const char* RepoGenStr = this->GetOption(RepoGenOpt);
- if (!RepoGenStr || cmIsNOTFOUND(RepoGenStr)) {
+ cmValue repoGen = this->GetOption(RepoGenOpt);
+ if (!repoGen || cmIsNOTFOUND(repoGen)) {
this->RepoGen.clear();
} else {
- this->RepoGen = RepoGenStr;
+ this->RepoGen = *repoGen;
}
// Framework version
- if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) {
- this->FrameworkVersion = FrameworkVersionSrt;
+ if (cmValue frameworkVersion = this->GetOption(FrameworkVersionOpt)) {
+ this->FrameworkVersion = *frameworkVersion;
} else {
this->FrameworkVersion = "1.9.9";
}
@@ -312,14 +313,13 @@ int cmCPackIFWGenerator::InitializeInternal()
// Additional packages dirs
this->PkgsDirsVector.clear();
- if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
+ if (cmValue dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) {
cmExpandList(dirs, this->PkgsDirsVector);
}
// Additional repositories dirs
this->RepoDirsVector.clear();
- if (const char* dirs =
- this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) {
+ if (cmValue dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) {
cmExpandList(dirs, this->RepoDirsVector);
}
@@ -330,22 +330,22 @@ int cmCPackIFWGenerator::InitializeInternal()
// Repository
this->Repository.Generator = this;
this->Repository.Name = "Unspecified";
- if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
- this->Repository.Url = site;
+ if (cmValue site = this->GetOption("CPACK_DOWNLOAD_SITE")) {
+ this->Repository.Url = *site;
this->Installer.RemoteRepositories.push_back(&this->Repository);
}
// Repositories
- if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) {
+ if (cmValue RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) {
std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr);
for (std::string const& r : RepoAllVector) {
this->GetRepository(r);
}
}
- if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
+ if (cmValue ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
this->OnlineOnly = cmIsOn(ifwDownloadAll);
- } else if (const char* cpackDownloadAll =
+ } else if (cmValue cpackDownloadAll =
this->GetOption("CPACK_DOWNLOAD_ALL")) {
this->OnlineOnly = cmIsOn(cpackDownloadAll);
} else {
@@ -374,9 +374,9 @@ int cmCPackIFWGenerator::InitializeInternal()
}
// Output extension
- if (const char* optOutExt =
+ if (cmValue optOutExt =
this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) {
- this->OutputExtension = optOutExt;
+ this->OutputExtension = *optOutExt;
} else if (sysName == "Darwin") {
this->OutputExtension = ".dmg";
} else {
@@ -508,21 +508,20 @@ std::string cmCPackIFWGenerator::GetRootPackageName()
{
// Default value
std::string name = "root";
- if (const char* optIFW_PACKAGE_GROUP =
+ if (cmValue optIFW_PACKAGE_GROUP =
this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
// Configure from root group
cmCPackIFWPackage package;
package.Generator = this;
package.ConfigureFromGroup(optIFW_PACKAGE_GROUP);
name = package.Name;
- } else if (const char* optIFW_PACKAGE_NAME =
+ } else if (cmValue optIFW_PACKAGE_NAME =
this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
// Configure from root package name
- name = optIFW_PACKAGE_NAME;
- } else if (const char* optPACKAGE_NAME =
- this->GetOption("CPACK_PACKAGE_NAME")) {
+ name = *optIFW_PACKAGE_NAME;
+ } else if (cmValue optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) {
// Configure from package name
- name = optPACKAGE_NAME;
+ name = *optPACKAGE_NAME;
}
return name;
}
@@ -537,10 +536,10 @@ std::string cmCPackIFWGenerator::GetGroupPackageName(
if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) {
return package->Name;
}
- const char* option =
+ cmValue option =
this->GetOption("CPACK_IFW_COMPONENT_GROUP_" +
cmsys::SystemTools::UpperCase(group->Name) + "_NAME");
- name = option ? option : group->Name;
+ name = option ? *option : group->Name;
if (group->ParentGroup) {
cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup);
bool dot = !this->ResolveDuplicateNames;
@@ -563,8 +562,8 @@ std::string cmCPackIFWGenerator::GetComponentPackageName(
}
std::string prefix = "CPACK_IFW_COMPONENT_" +
cmsys::SystemTools::UpperCase(component->Name) + "_";
- const char* option = this->GetOption(prefix + "NAME");
- name = option ? option : component->Name;
+ cmValue option = this->GetOption(prefix + "NAME");
+ name = option ? *option : component->Name;
if (component->Group) {
cmCPackIFWPackage* package = this->GetGroupPackage(component->Group);
if ((this->componentPackageMethod ==
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index bf8b457b4..7ee6300b8 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -14,6 +14,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
@@ -33,61 +34,60 @@ void cmCPackIFWInstaller::printSkippedOptionWarning(
void cmCPackIFWInstaller::ConfigureFromOptions()
{
// Name;
- if (const char* optIFW_PACKAGE_NAME =
+ if (cmValue optIFW_PACKAGE_NAME =
this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
- this->Name = optIFW_PACKAGE_NAME;
- } else if (const char* optPACKAGE_NAME =
- this->GetOption("CPACK_PACKAGE_NAME")) {
- this->Name = optPACKAGE_NAME;
+ this->Name = *optIFW_PACKAGE_NAME;
+ } else if (cmValue optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) {
+ this->Name = *optPACKAGE_NAME;
} else {
this->Name = "Your package";
}
// Title;
- if (const char* optIFW_PACKAGE_TITLE =
+ if (cmValue optIFW_PACKAGE_TITLE =
this->GetOption("CPACK_IFW_PACKAGE_TITLE")) {
- this->Title = optIFW_PACKAGE_TITLE;
- } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
+ this->Title = *optIFW_PACKAGE_TITLE;
+ } else if (cmValue optPACKAGE_DESCRIPTION_SUMMARY =
this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
- this->Title = optPACKAGE_DESCRIPTION_SUMMARY;
+ this->Title = *optPACKAGE_DESCRIPTION_SUMMARY;
} else {
this->Title = "Your package description";
}
// Version;
- if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
- this->Version = option;
+ if (cmValue option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = *option;
} else {
this->Version = "1.0.0";
}
// Publisher
- if (const char* optIFW_PACKAGE_PUBLISHER =
+ if (cmValue optIFW_PACKAGE_PUBLISHER =
this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
- this->Publisher = optIFW_PACKAGE_PUBLISHER;
- } else if (const char* optPACKAGE_VENDOR =
+ this->Publisher = *optIFW_PACKAGE_PUBLISHER;
+ } else if (cmValue optPACKAGE_VENDOR =
this->GetOption("CPACK_PACKAGE_VENDOR")) {
- this->Publisher = optPACKAGE_VENDOR;
+ this->Publisher = *optPACKAGE_VENDOR;
}
// ProductUrl
- if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) {
- this->ProductUrl = option;
+ if (cmValue option = this->GetOption("CPACK_IFW_PRODUCT_URL")) {
+ this->ProductUrl = *option;
}
// ApplicationIcon
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) {
if (cmSystemTools::FileExists(option)) {
- this->InstallerApplicationIcon = option;
+ this->InstallerApplicationIcon = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option);
}
}
// WindowIcon
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
if (cmSystemTools::FileExists(option)) {
- this->InstallerWindowIcon = option;
+ this->InstallerWindowIcon = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option);
}
@@ -103,45 +103,45 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// Logo
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
if (cmSystemTools::FileExists(option)) {
- this->Logo = option;
+ this->Logo = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option);
}
}
// Watermark
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) {
if (cmSystemTools::FileExists(option)) {
- this->Watermark = option;
+ this->Watermark = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option);
}
}
// Banner
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) {
if (cmSystemTools::FileExists(option)) {
- this->Banner = option;
+ this->Banner = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option);
}
}
// Background
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) {
if (cmSystemTools::FileExists(option)) {
- this->Background = option;
+ this->Background = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option);
}
}
// WizardStyle
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) {
// Setting the user value in any case
- this->WizardStyle = option;
+ this->WizardStyle = *option;
// Check known values
if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" &&
this->WizardStyle != "Mac" && this->WizardStyle != "Classic") {
@@ -154,28 +154,28 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// StyleSheet
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) {
if (cmSystemTools::FileExists(option)) {
- this->StyleSheet = option;
+ this->StyleSheet = *option;
} else {
this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_STYLE_SHEET", option);
}
}
// WizardDefaultWidth
- if (const char* option =
+ if (cmValue option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
- this->WizardDefaultWidth = option;
+ this->WizardDefaultWidth = *option;
}
// WizardDefaultHeight
- if (const char* option =
+ if (cmValue option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
- this->WizardDefaultHeight = option;
+ this->WizardDefaultHeight = *option;
}
// WizardShowPageList
- if (const char* option =
+ if (cmValue option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) {
if (!this->IsVersionLess("4.0")) {
if (this->IsSetToOff("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) {
@@ -204,23 +204,23 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// TitleColor
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
- this->TitleColor = option;
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
+ this->TitleColor = *option;
}
// Start menu
- if (const char* optIFW_START_MENU_DIR =
+ if (cmValue optIFW_START_MENU_DIR =
this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
- this->StartMenuDir = optIFW_START_MENU_DIR;
+ this->StartMenuDir = *optIFW_START_MENU_DIR;
} else {
this->StartMenuDir = this->Name;
}
// Default target directory for installation
- if (const char* optIFW_TARGET_DIRECTORY =
+ if (cmValue optIFW_TARGET_DIRECTORY =
this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
- this->TargetDir = optIFW_TARGET_DIRECTORY;
- } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
+ this->TargetDir = *optIFW_TARGET_DIRECTORY;
+ } else if (cmValue optPACKAGE_INSTALL_DIRECTORY =
this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
this->TargetDir =
cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY);
@@ -229,21 +229,20 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// Default target directory for installation with administrator rights
- if (const char* option =
- this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
- this->AdminTargetDir = option;
+ if (cmValue option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
+ this->AdminTargetDir = *option;
}
// Maintenance tool
- if (const char* optIFW_MAINTENANCE_TOOL =
+ if (cmValue optIFW_MAINTENANCE_TOOL =
this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
- this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
+ this->MaintenanceToolName = *optIFW_MAINTENANCE_TOOL;
}
// Maintenance tool ini file
- if (const char* optIFW_MAINTENANCE_TOOL_INI =
+ if (cmValue optIFW_MAINTENANCE_TOOL_INI =
this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
- this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
+ this->MaintenanceToolIniFile = *optIFW_MAINTENANCE_TOOL_INI;
}
// Allow non-ASCII characters
@@ -265,13 +264,13 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// Control script
- if (const char* optIFW_CONTROL_SCRIPT =
+ if (cmValue optIFW_CONTROL_SCRIPT =
this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
- this->ControlScript = optIFW_CONTROL_SCRIPT;
+ this->ControlScript = *optIFW_CONTROL_SCRIPT;
}
// Resources
- if (const char* optIFW_PACKAGE_RESOURCES =
+ if (cmValue optIFW_PACKAGE_RESOURCES =
this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
this->Resources.clear();
cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources);
@@ -541,7 +540,7 @@ void cmCPackIFWInstaller::GeneratePackageFiles()
package.Generator = this->Generator;
package.Installer = this;
// Check package group
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
+ if (cmValue option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) {
package.ConfigureFromGroup(option);
std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx
index 1429c4670..c2109c967 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -18,6 +18,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
//---------------------------------------------------------- CompareStruct ---
@@ -124,10 +125,10 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
if (!component) {
return "";
}
- const char* option =
+ cmValue option =
this->GetOption("CPACK_IFW_COMPONENT_" +
cmsys::SystemTools::UpperCase(component->Name) + "_NAME");
- return option ? option : component->Name;
+ return option ? *option : component->Name;
}
void cmCPackIFWPackage::DefaultConfiguration()
@@ -159,23 +160,22 @@ int cmCPackIFWPackage::ConfigureFromOptions()
this->Name = this->Generator->GetRootPackageName();
// Display name
- if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) {
- this->DisplayName[""] = option;
+ if (cmValue option = this->GetOption("CPACK_PACKAGE_NAME")) {
+ this->DisplayName[""] = *option;
} else {
this->DisplayName[""] = "Your package";
}
// Description
- if (const char* option =
- this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
- this->Description[""] = option;
+ if (cmValue option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
+ this->Description[""] = *option;
} else {
this->Description[""] = "Your package description";
}
// Version
- if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) {
- this->Version = option;
+ if (cmValue option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = *option;
} else {
this->Version = "1.0.0";
}
@@ -204,22 +204,22 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
this->Description[""] = component->Description;
// Version
- if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
- this->Version = optVERSION;
- } else if (const char* optPACKAGE_VERSION =
+ if (cmValue optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = *optVERSION;
+ } else if (cmValue optPACKAGE_VERSION =
this->GetOption("CPACK_PACKAGE_VERSION")) {
- this->Version = optPACKAGE_VERSION;
+ this->Version = *optPACKAGE_VERSION;
} else {
this->Version = "1.0.0";
}
// Script
- if (const char* option = this->GetOption(prefix + "SCRIPT")) {
- this->Script = option;
+ if (cmValue option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = *option;
}
// User interfaces
- if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ if (cmValue option = this->GetOption(prefix + "USER_INTERFACES")) {
this->UserInterfaces.clear();
cmExpandList(option, this->UserInterfaces);
}
@@ -232,7 +232,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
}
// Licenses
- if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ if (cmValue option = this->GetOption(prefix + "LICENSES")) {
this->Licenses.clear();
cmExpandList(option, this->Licenses);
if (this->Licenses.size() % 2 != 0) {
@@ -246,8 +246,8 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component)
}
// Priority
- if (const char* option = this->GetOption(prefix + "PRIORITY")) {
- this->SortingPriority = option;
+ if (cmValue option = this->GetOption(prefix + "PRIORITY")) {
+ this->SortingPriority = *option;
cmCPackIFWLogger(
WARNING,
"The \"PRIORITY\" option is set "
@@ -289,28 +289,28 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
this->Description[""] = group->Description;
// Version
- if (const char* optVERSION = this->GetOption(prefix + "VERSION")) {
- this->Version = optVERSION;
- } else if (const char* optPACKAGE_VERSION =
+ if (cmValue optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = *optVERSION;
+ } else if (cmValue optPACKAGE_VERSION =
this->GetOption("CPACK_PACKAGE_VERSION")) {
- this->Version = optPACKAGE_VERSION;
+ this->Version = *optPACKAGE_VERSION;
} else {
this->Version = "1.0.0";
}
// Script
- if (const char* option = this->GetOption(prefix + "SCRIPT")) {
- this->Script = option;
+ if (cmValue option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = *option;
}
// User interfaces
- if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ if (cmValue option = this->GetOption(prefix + "USER_INTERFACES")) {
this->UserInterfaces.clear();
cmExpandList(option, this->UserInterfaces);
}
// Licenses
- if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ if (cmValue option = this->GetOption(prefix + "LICENSES")) {
this->Licenses.clear();
cmExpandList(option, this->Licenses);
if (this->Licenses.size() % 2 != 0) {
@@ -324,8 +324,8 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group)
}
// Priority
- if (const char* option = this->GetOption(prefix + "PRIORITY")) {
- this->SortingPriority = option;
+ if (cmValue option = this->GetOption(prefix + "PRIORITY")) {
+ this->SortingPriority = *option;
cmCPackIFWLogger(
WARNING,
"The \"PRIORITY\" option is set "
@@ -346,14 +346,14 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName)
std::string prefix =
"CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_";
- if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) {
- group.DisplayName = option;
+ if (cmValue option = this->GetOption(prefix + "DISPLAY_NAME")) {
+ group.DisplayName = *option;
} else {
group.DisplayName = group.Name;
}
- if (const char* option = this->GetOption(prefix + "DESCRIPTION")) {
- group.Description = option;
+ if (cmValue option = this->GetOption(prefix + "DESCRIPTION")) {
+ group.Description = *option;
}
group.IsBold = this->IsOn(prefix + "BOLD_TITLE");
group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED");
@@ -381,7 +381,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "DISPLAY_NAME";
if (this->IsSetToEmpty(option)) {
this->DisplayName.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName);
}
@@ -389,7 +389,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "DESCRIPTION";
if (this->IsSetToEmpty(option)) {
this->Description.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
cmCPackIFWPackage::ExpandListArgument(value, this->Description);
}
@@ -397,31 +397,31 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "RELEASE_DATE";
if (this->IsSetToEmpty(option)) {
this->ReleaseDate.clear();
- } else if (const char* value = this->GetOption(option)) {
- this->ReleaseDate = value;
+ } else if (cmValue value = this->GetOption(option)) {
+ this->ReleaseDate = *value;
}
// Sorting priority
option = prefix + "SORTING_PRIORITY";
if (this->IsSetToEmpty(option)) {
this->SortingPriority.clear();
- } else if (const char* value = this->GetOption(option)) {
- this->SortingPriority = value;
+ } else if (cmValue value = this->GetOption(option)) {
+ this->SortingPriority = *value;
}
// Update text
option = prefix + "UPDATE_TEXT";
if (this->IsSetToEmpty(option)) {
this->UpdateText.clear();
- } else if (const char* value = this->GetOption(option)) {
- this->UpdateText = value;
+ } else if (cmValue value = this->GetOption(option)) {
+ this->UpdateText = *value;
}
// Translations
option = prefix + "TRANSLATIONS";
if (this->IsSetToEmpty(option)) {
this->Translations.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
this->Translations.clear();
cmExpandList(value, this->Translations);
}
@@ -429,11 +429,11 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
// QtIFW dependencies
std::vector<std::string> deps;
option = prefix + "DEPENDS";
- if (const char* value = this->GetOption(option)) {
+ if (cmValue value = this->GetOption(option)) {
cmExpandList(value, deps);
}
option = prefix + "DEPENDENCIES";
- if (const char* value = this->GetOption(option)) {
+ if (cmValue value = this->GetOption(option)) {
cmExpandList(value, deps);
}
for (std::string const& d : deps) {
@@ -454,7 +454,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "AUTO_DEPEND_ON";
if (this->IsSetToEmpty(option)) {
this->AlienAutoDependOn.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
std::vector<std::string> depsOn = cmExpandedList(value);
for (std::string const& d : depsOn) {
DependenceStruct dep(d);
@@ -483,7 +483,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "DEFAULT";
if (this->IsSetToEmpty(option)) {
this->Default.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
std::string lowerValue = cmsys::SystemTools::LowerCase(value);
if (lowerValue == "true") {
this->Default = "true";
@@ -492,7 +492,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
} else if (lowerValue == "script") {
this->Default = "script";
} else {
- this->Default = value;
+ this->Default = *value;
}
}
@@ -510,7 +510,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix)
option = prefix + "REPLACES";
if (this->IsSetToEmpty(option)) {
this->Replaces.clear();
- } else if (const char* value = this->GetOption(option)) {
+ } else if (cmValue value = this->GetOption(option)) {
this->Replaces.clear();
cmExpandList(value, this->Replaces);
}
diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx
index 7ec225686..f25d2d28c 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.cxx
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -7,6 +7,7 @@
#include "cmCPackIFWGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
@@ -55,22 +56,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions()
}
// Url
- if (const char* url = this->GetOption(prefix + "URL")) {
- this->Url = url;
+ if (cmValue url = this->GetOption(prefix + "URL")) {
+ this->Url = *url;
} else {
this->Url.clear();
}
// Old url
- if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) {
- this->OldUrl = oldUrl;
+ if (cmValue oldUrl = this->GetOption(prefix + "OLD_URL")) {
+ this->OldUrl = *oldUrl;
} else {
this->OldUrl.clear();
}
// New url
- if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) {
- this->NewUrl = newUrl;
+ if (cmValue newUrl = this->GetOption(prefix + "NEW_URL")) {
+ this->NewUrl = *newUrl;
} else {
this->NewUrl.clear();
}
@@ -83,22 +84,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions()
}
// Username
- if (const char* username = this->GetOption(prefix + "USERNAME")) {
- this->Username = username;
+ if (cmValue username = this->GetOption(prefix + "USERNAME")) {
+ this->Username = *username;
} else {
this->Username.clear();
}
// Password
- if (const char* password = this->GetOption(prefix + "PASSWORD")) {
- this->Password = password;
+ if (cmValue password = this->GetOption(prefix + "PASSWORD")) {
+ this->Password = *password;
} else {
this->Password.clear();
}
// DisplayName
- if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
- this->DisplayName = displayName;
+ if (cmValue displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
+ this->DisplayName = *displayName;
} else {
this->DisplayName.clear();
}
diff --git a/Source/CPack/OSXScriptLauncher.cxx b/Source/CPack/OSXScriptLauncher.cxx
index bdaf779af..b7140abd7 100644
--- a/Source/CPack/OSXScriptLauncher.cxx
+++ b/Source/CPack/OSXScriptLauncher.cxx
@@ -118,5 +118,5 @@ int main(int argc, char* argv[])
cmsysProcess_Delete(cp);
- return 0;
+ return !result;
}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 8b3644f91..d03239b52 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUuid.h"
+#include "cmValue.h"
#include "cmWIXDirectoriesSourceWriter.h"
#include "cmWIXFeaturesSourceWriter.h"
#include "cmWIXFilesSourceWriter.h"
@@ -125,7 +126,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
command << " -ext " << QuotePath(ext);
}
- const char* const cultures = GetOption("CPACK_WIX_CULTURES");
+ cmValue const cultures = GetOption("CPACK_WIX_CULTURES");
if (cultures) {
command << " -cultures:" << cultures;
}
@@ -156,18 +157,18 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
return false;
}
- if (GetOption("CPACK_WIX_PRODUCT_GUID") == 0) {
+ if (!GetOption("CPACK_WIX_PRODUCT_GUID")) {
std::string guid = GenerateGUID();
- SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str());
+ SetOption("CPACK_WIX_PRODUCT_GUID", guid);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . "
<< std::endl);
}
- if (GetOption("CPACK_WIX_UPGRADE_GUID") == 0) {
+ if (!GetOption("CPACK_WIX_UPGRADE_GUID")) {
std::string guid = GenerateGUID();
- SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str());
+ SetOption("CPACK_WIX_UPGRADE_GUID", guid);
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_WIX_UPGRADE_GUID implicitly set to "
@@ -182,36 +183,36 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
return false;
}
- if (GetOption("CPACK_WIX_LICENSE_RTF") == 0) {
+ if (!GetOption("CPACK_WIX_LICENSE_RTF")) {
std::string licenseFilename = this->CPackTopLevel + "/License.rtf";
- SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str());
+ SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename);
if (!CreateLicenseFile()) {
return false;
}
}
- if (GetOption("CPACK_PACKAGE_VENDOR") == 0) {
+ if (!GetOption("CPACK_PACKAGE_VENDOR")) {
std::string defaultVendor = "Humanity";
- SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str());
+ SetOption("CPACK_PACKAGE_VENDOR", defaultVendor);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"CPACK_PACKAGE_VENDOR implicitly set to "
<< defaultVendor << " . " << std::endl);
}
- if (GetOption("CPACK_WIX_UI_REF") == 0) {
+ if (!GetOption("CPACK_WIX_UI_REF")) {
std::string defaultRef = "WixUI_InstallDir";
if (!this->Components.empty()) {
defaultRef = "WixUI_FeatureTree";
}
- SetOption("CPACK_WIX_UI_REF", defaultRef.c_str());
+ SetOption("CPACK_WIX_UI_REF", defaultRef);
}
- const char* packageContact = GetOption("CPACK_PACKAGE_CONTACT");
- if (packageContact != 0 && GetOption("CPACK_WIX_PROPERTY_ARPCONTACT") == 0) {
+ cmValue packageContact = GetOption("CPACK_PACKAGE_CONTACT");
+ if (packageContact && !GetOption("CPACK_WIX_PROPERTY_ARPCONTACT")) {
SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact);
}
@@ -223,7 +224,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions);
CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces);
- const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
+ cmValue patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
if (patchFilePath) {
std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath);
@@ -295,7 +296,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
void cmCPackWIXGenerator::AppendUserSuppliedExtraSources()
{
- const char* cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES");
+ cmValue cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES");
if (!cpackWixExtraSources)
return;
@@ -304,7 +305,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources()
void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream)
{
- const char* cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS");
+ cmValue cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS");
if (!cpackWixExtraObjects)
return;
@@ -355,7 +356,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
for (std::string const& name : options) {
if (cmHasPrefix(name, prefix)) {
std::string id = name.substr(prefix.length());
- std::string value = GetOption(name.c_str());
+ std::string value = GetOption(name);
includeFile.BeginElement("Property");
includeFile.AddAttribute("Id", id);
@@ -364,7 +365,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile()
}
}
- if (GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION") == 0) {
+ if (!GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION")) {
includeFile.BeginElement("Property");
includeFile.AddAttribute("Id", "INSTALL_ROOT");
includeFile.AddAttribute("Secure", "yes");
@@ -405,7 +406,7 @@ void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source,
std::string const& name,
DefinitionType type)
{
- const char* value = GetOption(name.c_str());
+ cmValue value = GetOption(name);
if (value) {
if (type == DefinitionType::PATH) {
AddDefinition(source, name, CMakeToWixPath(value));
@@ -485,17 +486,17 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
}
std::string featureTitle = cpackPackageName;
- if (const char* title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) {
- featureTitle = title;
+ if (cmValue title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) {
+ featureTitle = *title;
}
featureDefinitions.AddAttribute("Title", featureTitle);
- if (const char* desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) {
+ if (cmValue desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) {
featureDefinitions.AddAttribute("Description", desc);
}
featureDefinitions.AddAttribute("Level", "1");
this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions);
- const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
+ cmValue package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
if (package) {
featureDefinitions.CreateCMakePackageRegistryEntry(
package, GetOption("CPACK_WIX_UPGRADE_GUID"));
@@ -540,10 +541,9 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
}
bool emitUninstallShortcut = true;
- const char* cpackWixProgramMenuFolder =
+ cmValue cpackWixProgramMenuFolder =
GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
- if (cpackWixProgramMenuFolder &&
- cm::string_view(cpackWixProgramMenuFolder) == ".") {
+ if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") {
emitUninstallShortcut = false;
} else if (emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) ==
emittedShortcutTypes.end()) {
@@ -595,9 +595,9 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const
std::string result = "ProgramFiles<64>Folder";
- const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID");
+ cmValue rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID");
if (rootFolderId) {
- result = rootFolderId;
+ result = *rootFolderId;
}
if (GetArchitecture() == "x86") {
@@ -612,8 +612,8 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const
bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate()
{
std::string wixTemplate = FindTemplate("WIX.template.in");
- if (GetOption("CPACK_WIX_TEMPLATE") != 0) {
- wixTemplate = GetOption("CPACK_WIX_TEMPLATE");
+ if (cmValue wixtpl = GetOption("CPACK_WIX_TEMPLATE")) {
+ wixTemplate = *wixtpl;
}
if (wixTemplate.empty()) {
@@ -669,7 +669,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
featureDefinitions.AddAttribute("Id", featureId);
std::vector<std::string> cpackPackageExecutablesList;
- const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
+ cmValue cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
if (cpackPackageExecutables) {
cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList);
if (cpackPackageExecutablesList.size() % 2 != 0) {
@@ -683,8 +683,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature(
}
std::vector<std::string> cpackPackageDesktopLinksList;
- const char* cpackPackageDesktopLinks =
- GetOption("CPACK_CREATE_DESKTOP_LINKS");
+ cmValue cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS");
if (cpackPackageDesktopLinks) {
cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList);
}
@@ -743,10 +742,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType(
std::string directoryId;
switch (type) {
case cmWIXShortcuts::START_MENU: {
- const char* cpackWixProgramMenuFolder =
+ cmValue cpackWixProgramMenuFolder =
GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
- if (cpackWixProgramMenuFolder &&
- cm::string_view(cpackWixProgramMenuFolder) == ".") {
+ if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") {
directoryId = "ProgramMenuFolder";
} else {
directoryId = "PROGRAM_MENU_FOLDER";
@@ -805,10 +803,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType(
fileDefinitions);
if (type == cmWIXShortcuts::START_MENU) {
- const char* cpackWixProgramMenuFolder =
+ cmValue cpackWixProgramMenuFolder =
GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
- if (cpackWixProgramMenuFolder &&
- cm::string_view(cpackWixProgramMenuFolder) != ".") {
+ if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder != ".") {
fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" +
idSuffix);
}
@@ -973,9 +970,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions(
bool cmCPackWIXGenerator::RequireOption(std::string const& name,
std::string& value) const
{
- const char* tmp = GetOption(name.c_str());
+ cmValue tmp = GetOption(name);
if (tmp) {
- value = tmp;
+ value = *tmp;
return true;
} else {
@@ -1146,7 +1143,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c)
void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName,
extension_set_t& extensions)
{
- const char* variableContent = GetOption(variableName.c_str());
+ cmValue variableContent = GetOption(variableName);
if (!variableContent)
return;
@@ -1157,7 +1154,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName,
void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName,
xmlns_map_t& namespaces)
{
- const char* variableContent = GetOption(variableName.c_str());
+ cmValue variableContent = GetOption(variableName);
if (!variableContent) {
return;
}
@@ -1180,13 +1177,13 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName,
oss << " xmlns:" << ns.first << "=\""
<< cmWIXSourceWriter::EscapeAttributeValue(ns.second) << '"';
}
- SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str().c_str());
+ SetOption("CPACK_WIX_CUSTOM_XMLNS_EXPANDED", oss.str());
}
void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName,
std::ostream& stream)
{
- const char* variableContent = GetOption(variableName.c_str());
+ cmValue variableContent = GetOption(variableName);
if (!variableContent)
return;
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index d9234e666..56e8463c1 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackArchiveGenerator.h"
-#include <cstdlib>
#include <cstring>
#include <map>
#include <ostream>
@@ -15,6 +14,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmWorkingDirectory.h"
cmCPackGenerator* cmCPackArchiveGenerator::Create7ZGenerator()
@@ -77,7 +77,7 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName(
if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) {
packageFileName +=
- this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME");
+ *this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME");
} else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
packageFileName += this->GetComponentPackageFileName(
this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName);
@@ -118,11 +118,11 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/');
}
- const char* installPrefix =
- this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
- if (installPrefix && installPrefix[0] == '/' && installPrefix[1] != 0) {
+ cmValue installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ if (installPrefix && installPrefix->size() > 1 &&
+ (*installPrefix)[0] == '/') {
// add to file prefix and remove the leading '/'
- filePrefix += installPrefix + 1;
+ filePrefix += installPrefix->substr(1);
filePrefix += "/";
}
for (std::string const& file : component->Files) {
@@ -257,9 +257,9 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
this->packageFileNames[0] += "/";
if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
- this->packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME");
+ this->packageFileNames[0] += *this->GetOption("CPACK_ARCHIVE_FILE_NAME");
} else {
- this->packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ this->packageFileNames[0] += *this->GetOption("CPACK_PACKAGE_FILE_NAME");
}
this->packageFileNames[0] += this->GetOutputExtension();
@@ -345,9 +345,9 @@ int cmCPackArchiveGenerator::GetThreadCount() const
// CPACK_ARCHIVE_THREADS overrides CPACK_THREADS
if (this->IsSet("CPACK_ARCHIVE_THREADS")) {
- threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS"));
+ threads = std::stoi(this->GetOption("CPACK_ARCHIVE_THREADS"));
} else if (this->IsSet("CPACK_THREADS")) {
- threads = std::atoi(this->GetOption("CPACK_THREADS"));
+ threads = std::stoi(this->GetOption("CPACK_THREADS"));
}
return threads;
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
index 4d5f43f9e..b3d425aa5 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -8,6 +8,7 @@
#include "cmCPackLog.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackBundleGenerator::cmCPackBundleGenerator() = default;
@@ -15,8 +16,8 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() = default;
int cmCPackBundleGenerator::InitializeInternal()
{
- const char* name = this->GetOption("CPACK_BUNDLE_NAME");
- if (nullptr == name) {
+ cmValue name = this->GetOption("CPACK_BUNDLE_NAME");
+ if (!name) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_BUNDLE_NAME must be set to use the Bundle generator."
<< std::endl);
@@ -33,7 +34,7 @@ int cmCPackBundleGenerator::InitializeInternal()
"Cannot locate codesign command" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path);
}
return this->Superclass::InitializeInternal();
@@ -51,30 +52,24 @@ int cmCPackBundleGenerator::ConstructBundle()
{
// Get required arguments ...
- const std::string cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME")
- ? this->GetOption("CPACK_BUNDLE_NAME")
- : "";
- if (cpack_bundle_name.empty()) {
+ cmValue cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME");
+ if (cpack_bundle_name->empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_BUNDLE_NAME must be set." << std::endl);
return 0;
}
- const std::string cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST")
- ? this->GetOption("CPACK_BUNDLE_PLIST")
- : "";
- if (cpack_bundle_plist.empty()) {
+ cmValue cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST");
+ if (cpack_bundle_plist->empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_BUNDLE_PLIST must be set." << std::endl);
return 0;
}
- const std::string cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON")
- ? this->GetOption("CPACK_BUNDLE_ICON")
- : "";
- if (cpack_bundle_icon.empty()) {
+ cmValue cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON");
+ if (cpack_bundle_icon->empty()) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_BUNDLE_ICON must be set." << std::endl);
@@ -82,10 +77,8 @@ int cmCPackBundleGenerator::ConstructBundle()
}
// Get optional arguments ...
- const std::string cpack_bundle_startup_command =
- this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
- ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND")
- : "";
+ cmValue cpack_bundle_startup_command =
+ this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND");
// The staging directory contains everything that will end-up inside the
// final disk image ...
@@ -138,7 +131,7 @@ int cmCPackBundleGenerator::ConstructBundle()
// Optionally a user-provided startup command (could be an
// executable or a script) ...
- if (!cpack_bundle_startup_command.empty()) {
+ if (!cpack_bundle_startup_command->empty()) {
std::ostringstream command_source;
command_source << cpack_bundle_startup_command;
@@ -180,13 +173,11 @@ bool cmCPackBundleGenerator::SupportsComponentInstallation() const
int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
{
- const std::string cpack_apple_cert_app =
- this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
- ? this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")
- : "";
+ cmValue cpack_apple_cert_app =
+ this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP");
// codesign the application.
- if (!cpack_apple_cert_app.empty()) {
+ if (!cpack_apple_cert_app->empty()) {
std::string output;
std::string bundle_path;
bundle_path =
@@ -195,13 +186,10 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
// A list of additional files to sign, ie. frameworks and plugins.
const std::string sign_parameter =
this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
- ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
+ ? *this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
: "--deep -f";
- const std::string sign_files =
- this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
- ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES")
- : "";
+ cmValue sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES");
std::vector<std::string> relFiles = cmExpandedList(sign_files);
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index b5abd5a6b..484db0038 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
cmCPackCygwinBinaryGenerator::cmCPackCygwinBinaryGenerator()
@@ -59,14 +60,15 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
const char* cmCPackCygwinBinaryGenerator::GetOutputExtension()
{
this->OutputExtension = "-";
- const char* patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
+ cmValue patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patchNumber) {
- patchNumber = "1";
+ this->OutputExtension += "1";
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_CYGWIN_PATCH_NUMBER not specified using 1"
<< std::endl);
+ } else {
+ this->OutputExtension += patchNumber;
}
- this->OutputExtension += patchNumber;
this->OutputExtension += ".tar.bz2";
return this->OutputExtension.c_str();
}
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 64a88eba4..59df380c5 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
// Includes needed for implementation of RenameFile. This is not in
@@ -94,14 +95,15 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
}
std::string outerTarFile =
cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-');
- const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
+ cmValue patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
- patch = "1";
+ outerTarFile += "1";
+ } else {
+ outerTarFile += patch;
}
- outerTarFile += patch;
outerTarFile += "-src.tar.bz2";
std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
std::string buildScript =
@@ -145,14 +147,15 @@ const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix()
const char* cmCPackCygwinSourceGenerator::GetOutputExtension()
{
this->OutputExtension = "-";
- const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
+ cmValue patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
if (!patch) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
"CPACK_CYGWIN_PATCH_NUMBER"
<< " not specified, defaulting to 1\n");
- patch = "1";
+ this->OutputExtension += "1";
+ } else {
+ this->OutputExtension += patch;
}
- this->OutputExtension += patch;
this->OutputExtension += "-src.tar.bz2";
return this->OutputExtension.c_str();
}
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index a1ebbdfb9..d7aa28717 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -2,11 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCPackDebGenerator.h"
-#include <cstdlib>
+#include <algorithm>
#include <cstring>
#include <map>
#include <ostream>
#include <set>
+#include <stdexcept>
#include <utility>
#include "cmsys/Glob.hxx"
@@ -21,6 +22,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
@@ -29,12 +31,12 @@ class DebGenerator
public:
DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir,
std::string topLevelDir, std::string temporaryDir,
- const char* debianCompressionType, const char* numThreads,
- const char* debianArchiveType,
+ cmValue debianCompressionType, cmValue numThreads,
+ cmValue debianArchiveType,
std::map<std::string, std::string> controlValues,
bool genShLibs, std::string shLibsFilename, bool genPostInst,
std::string postInst, bool genPostRm, std::string postRm,
- const char* controlExtra, bool permissionStrctPolicy,
+ cmValue controlExtra, bool permissionStrctPolicy,
std::vector<std::string> packageFiles);
bool generate() const;
@@ -53,8 +55,8 @@ private:
std::string CompressionSuffix;
const std::string TopLevelDir;
const std::string TemporaryDir;
- const char* DebianArchiveType;
- int NumThreads;
+ const std::string DebianArchiveType;
+ long NumThreads;
const std::map<std::string, std::string> ControlValues;
const bool GenShLibs;
const std::string ShLibsFilename;
@@ -62,7 +64,7 @@ private:
const std::string PostInst;
const bool GenPostRm;
const std::string PostRm;
- const char* ControlExtra;
+ cmValue ControlExtra;
const bool PermissionStrictPolicy;
const std::vector<std::string> PackageFiles;
cmArchiveWrite::Compress TarCompressionType;
@@ -71,18 +73,17 @@ private:
DebGenerator::DebGenerator(
cmCPackLog* logger, std::string outputName, std::string workDir,
std::string topLevelDir, std::string temporaryDir,
- const char* debianCompressionType, const char* numThreads,
- const char* debianArchiveType,
+ cmValue debCompressionType, cmValue numThreads, cmValue debianArchiveType,
std::map<std::string, std::string> controlValues, bool genShLibs,
std::string shLibsFilename, bool genPostInst, std::string postInst,
- bool genPostRm, std::string postRm, const char* controlExtra,
+ bool genPostRm, std::string postRm, cmValue controlExtra,
bool permissionStrictPolicy, std::vector<std::string> packageFiles)
: Logger(logger)
, OutputName(std::move(outputName))
, WorkDir(std::move(workDir))
, TopLevelDir(std::move(topLevelDir))
, TemporaryDir(std::move(temporaryDir))
- , DebianArchiveType(debianArchiveType ? debianArchiveType : "gnutar")
+ , DebianArchiveType(debianArchiveType ? *debianArchiveType : "gnutar")
, ControlValues(std::move(controlValues))
, GenShLibs(genShLibs)
, ShLibsFilename(std::move(shLibsFilename))
@@ -94,23 +95,27 @@ DebGenerator::DebGenerator(
, PermissionStrictPolicy(permissionStrictPolicy)
, PackageFiles(std::move(packageFiles))
{
- if (!debianCompressionType) {
- debianCompressionType = "gzip";
+ std::string debianCompressionType = "gzip";
+ if (debCompressionType) {
+ debianCompressionType = *debCompressionType;
}
- if (!strcmp(debianCompressionType, "lzma")) {
+ if (debianCompressionType == "lzma") {
this->CompressionSuffix = ".lzma";
this->TarCompressionType = cmArchiveWrite::CompressLZMA;
- } else if (!strcmp(debianCompressionType, "xz")) {
+ } else if (debianCompressionType == "xz") {
this->CompressionSuffix = ".xz";
this->TarCompressionType = cmArchiveWrite::CompressXZ;
- } else if (!strcmp(debianCompressionType, "bzip2")) {
+ } else if (debianCompressionType == "bzip2") {
this->CompressionSuffix = ".bz2";
this->TarCompressionType = cmArchiveWrite::CompressBZip2;
- } else if (!strcmp(debianCompressionType, "gzip")) {
+ } else if (debianCompressionType == "gzip") {
this->CompressionSuffix = ".gz";
this->TarCompressionType = cmArchiveWrite::CompressGZip;
- } else if (!strcmp(debianCompressionType, "none")) {
+ } else if (debianCompressionType == "zstd") {
+ this->CompressionSuffix = ".zst";
+ this->TarCompressionType = cmArchiveWrite::CompressZstd;
+ } else if (debianCompressionType == "none") {
this->CompressionSuffix.clear();
this->TarCompressionType = cmArchiveWrite::CompressNone;
} else {
@@ -119,16 +124,15 @@ DebGenerator::DebGenerator(
<< debianCompressionType << std::endl);
}
- if (numThreads == nullptr) {
- numThreads = "1";
- }
-
- char* endptr;
- this->NumThreads = static_cast<int>(strtol(numThreads, &endptr, 10));
- if (numThreads != endptr && *endptr != '\0') {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Unrecognized number of threads: " << numThreads
- << std::endl);
+ if (numThreads != nullptr) {
+ if (!cmStrToLong(numThreads, &this->NumThreads)) {
+ this->NumThreads = 1;
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Unrecognized number of threads: " << numThreads
+ << std::endl);
+ }
+ } else {
+ this->NumThreads = 1;
}
}
@@ -187,8 +191,15 @@ bool DebGenerator::generateDataTar() const
return false;
}
cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType,
- this->DebianArchiveType, 0, this->NumThreads);
- data_tar.Open();
+ this->DebianArchiveType, 0,
+ static_cast<int>(this->NumThreads));
+ if (!data_tar.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << filename_data_tar
+ << "\", ERROR = " << data_tar.GetError() << std::endl);
+ return false;
+ }
// uid/gid should be the one of the root user, and this root user has
// always uid/gid equal to 0.
@@ -248,11 +259,15 @@ bool DebGenerator::generateDataTar() const
// do not recurse because the loop will do it
if (!data_tar.Add(file, topLevelLength, ".", false)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: " << file << std::endl
- << "#error:" << data_tar.GetError() << std::endl);
+ "Problem adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: "
+ << file
+ << "\n"
+ "#error:"
+ << data_tar.GetError() << std::endl);
return false;
}
}
@@ -309,7 +324,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
cmArchiveWrite control_tar(fileStream_control_tar,
cmArchiveWrite::CompressGZip,
this->DebianArchiveType);
- control_tar.Open();
+ if (!control_tar.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << filename_control_tar
+ << "\", ERROR = " << control_tar.GetError() << std::endl);
+ return false;
+ }
// sets permissions and uid/gid for the files
control_tar.SetUIDAndGID(0u, 0u);
@@ -334,11 +355,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
!control_tar.Add(this->WorkDir + "/control", this->WorkDir.length(),
".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"control\" or \"md5sums\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"control\" or \"md5sums\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
@@ -346,11 +369,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
if (this->GenShLibs) {
if (!control_tar.Add(this->ShLibsFilename, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"shlibs\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"shlibs\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
}
@@ -360,11 +385,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission755);
if (!control_tar.Add(this->PostInst, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"postinst\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
control_tar.SetPermissions(permission644);
@@ -374,11 +401,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
control_tar.SetPermissions(permission755);
if (!control_tar.Add(this->PostRm, this->WorkDir.length(), ".")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error adding file to tar:"
- << std::endl
- << "#top level directory: " << this->WorkDir << std::endl
- << "#file: \"postinst\"" << std::endl
- << "#error:" << control_tar.GetError() << std::endl);
+ "Error adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#file: \"postinst\"\n"
+ "#error:"
+ << control_tar.GetError() << std::endl);
return false;
}
control_tar.SetPermissions(permission644);
@@ -412,11 +441,12 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const
// if we can copy the file, it means it does exist, let's add it:
if (!cmsys::SystemTools::FileExists(i)) {
cmCPackLogger(cmCPackLog::LOG_WARNING,
- "Adding file to tar:" << std::endl
- << "#top level directory: "
- << this->WorkDir << std::endl
- << "#missing file: " << i
- << std::endl);
+ "Adding file to tar:\n"
+ "#top level directory: "
+ << this->WorkDir
+ << "\n"
+ "#missing file: "
+ << i << std::endl);
}
if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) {
@@ -440,7 +470,13 @@ bool DebGenerator::generateDeb() const
cmGeneratedFileStream debStream;
debStream.Open(outputPath, false, true);
cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd");
- deb.Open();
+ if (!deb.Open()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error opening the archive \""
+ << outputPath << "\", ERROR = " << deb.GetError()
+ << std::endl);
+ return false;
+ }
// uid/gid should be the one of the root user, and this root user has
// always uid/gid equal to 0.
@@ -451,17 +487,37 @@ bool DebGenerator::generateDeb() const
!deb.Add(tlDir + "control.tar.gz", tlDir.length()) ||
!deb.Add(tlDir + "data.tar" + this->CompressionSuffix, tlDir.length())) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error creating debian package:"
- << std::endl
- << "#top level directory: " << this->TopLevelDir
- << std::endl
- << "#file: " << this->OutputName << std::endl
- << "#error:" << deb.GetError() << std::endl);
+ "Error creating debian package:\n"
+ "#top level directory: "
+ << this->TopLevelDir
+ << "\n"
+ "#file: "
+ << this->OutputName
+ << "\n"
+ "#error:"
+ << deb.GetError() << std::endl);
return false;
}
return true;
}
+std::vector<std::string> findFilesIn(const std::string& path)
+{
+ cmsys::Glob gl;
+ std::string findExpr = path + "/*";
+ gl.RecurseOn();
+ gl.SetRecurseListDirs(true);
+ gl.SetRecurseThroughSymlinks(false);
+ if (!gl.FindFiles(findExpr)) {
+ throw std::runtime_error(
+ "Cannot find any files in the installed directory");
+ }
+ std::vector<std::string> files{ gl.GetFiles() };
+ // Sort files so that they have a reproducible order
+ std::sort(files.begin(), files.end());
+ return files;
+}
+
} // end anonymous namespace
cmCPackDebGenerator::cmCPackDebGenerator() = default;
@@ -480,128 +536,71 @@ int cmCPackDebGenerator::InitializeInternal()
int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
std::string const& packageName)
{
- int retval = 1;
// Begin the archive for this pack
std::string localToplevel(initialTopLevel);
std::string packageFileName(
cmSystemTools::GetParentDirectory(this->toplevel));
- std::string outputFileName(
- std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + "-" +
- packageName + this->GetOutputExtension());
+ std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") +
+ "-" + packageName + this->GetOutputExtension());
localToplevel += "/" + packageName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel);
packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName);
/* replace the TEMPORARY package file name */
- this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
+ this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName);
// Tell CPackDeb.cmake the name of the component GROUP.
- this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str());
+ this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName);
// Tell CPackDeb.cmake the path where the component is.
std::string component_path = cmStrCat('/', packageName);
- this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
- component_path.c_str());
+ this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path);
if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackDeb.cmake" << std::endl);
- retval = 0;
- return retval;
- }
-
- { // Isolate globbing of binaries vs. dbgsyms
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_WDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
- }
- this->packageFiles = gl.GetFiles();
- }
-
- int res = this->createDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
-
- if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") &&
- this->GetOption("GEN_DBGSYMDIR")) {
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_DBGSYMDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
- return 0;
- }
- this->packageFiles = gl.GetFiles();
-
- res = this->createDbgsymDDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName =
- cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
+ return 0;
}
- return retval;
+ return this->createDebPackages();
}
int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
{
- int retval = 1;
- /* Reset package file name list it will be populated during the
- * component packaging run*/
+ // Reset package file name list it will be populated during the
+ // component packaging run
this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
+ int retval = 1;
// The default behavior is to have one package by component group
// unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
- if (!ignoreGroup) {
- for (auto const& compG : this->ComponentGroups) {
- cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Packaging component group: " << compG.first << std::endl);
- // Begin the archive for this group
- retval &= this->PackageOnePack(initialTopLevel, compG.first);
- }
- // Handle Orphan components (components not belonging to any groups)
+ if (ignoreGroup) {
+ // CPACK_COMPONENTS_IGNORE_GROUPS is set
+ // We build 1 package per component
for (auto const& comp : this->Components) {
- // Does the component belong to a group?
- if (comp.second.Group == nullptr) {
- cmCPackLogger(
- cmCPackLog::LOG_VERBOSE,
- "Component <"
- << comp.second.Name
- << "> does not belong to any group, package it separately."
- << std::endl);
- // Begin the archive for this orphan component
- retval &= this->PackageOnePack(initialTopLevel, comp.first);
- }
+ retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
+ return retval;
}
- // CPACK_COMPONENTS_IGNORE_GROUPS is set
- // We build 1 package per component
- else {
- for (auto const& comp : this->Components) {
+
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
+ // Begin the archive for this group
+ retval &= this->PackageOnePack(initialTopLevel, compG.first);
+ }
+ // Handle Orphan components (components not belonging to any groups)
+ for (auto const& comp : this->Components) {
+ // Does the component belong to a group?
+ if (comp.second.Group == nullptr) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE,
+ "Component <"
+ << comp.second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ // Begin the archive for this orphan component
retval &= this->PackageOnePack(initialTopLevel, comp.first);
}
}
@@ -612,7 +611,6 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup)
int cmCPackDebGenerator::PackageComponentsAllInOne(
const std::string& compInstDirName)
{
- int retval = 1;
/* Reset package file name list it will be populated during the
* component packaging run*/
this->packageFileNames.clear();
@@ -627,9 +625,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
std::string localToplevel(initialTopLevel);
std::string packageFileName(
cmSystemTools::GetParentDirectory(this->toplevel));
- std::string outputFileName(
- std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) +
- this->GetOutputExtension());
+ std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") +
+ this->GetOutputExtension());
// all GROUP in one vs all COMPONENT in one
// if must be here otherwise non component paths have a trailing / while
// components don't
@@ -638,50 +635,25 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
}
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel);
packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName);
/* replace the TEMPORARY package file name */
- this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
+ this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName);
if (!compInstDirName.empty()) {
// Tell CPackDeb.cmake the path where the component is.
std::string component_path = cmStrCat('/', compInstDirName);
- this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
- component_path.c_str());
+ this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path);
}
if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackDeb.cmake" << std::endl);
- retval = 0;
- return retval;
- }
-
- cmsys::Glob gl;
- std::string findExpr(this->GetOption("GEN_WDIR"));
- findExpr += "/*";
- gl.RecurseOn();
- gl.SetRecurseListDirs(true);
- gl.SetRecurseThroughSymlinks(false);
- if (!gl.FindFiles(findExpr)) {
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find any files in the installed directory"
- << std::endl);
return 0;
}
- this->packageFiles = gl.GetFiles();
- int res = this->createDeb();
- if (res != 1) {
- retval = 0;
- }
- // add the generated package to package file names list
- packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
- this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
- this->packageFileNames.push_back(std::move(packageFileName));
- return retval;
+ return this->createDebPackages();
}
int cmCPackDebGenerator::PackageFiles()
@@ -705,7 +677,40 @@ int cmCPackDebGenerator::PackageFiles()
return this->PackageComponentsAllInOne("");
}
-int cmCPackDebGenerator::createDeb()
+bool cmCPackDebGenerator::createDebPackages()
+{
+ auto make_package = [this](const std::string& path,
+ const char* const output_var,
+ bool (cmCPackDebGenerator::*creator)()) -> bool {
+ try {
+ this->packageFiles = findFilesIn(path);
+ } catch (const std::runtime_error& ex) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, ex.what() << std::endl);
+ return false;
+ }
+
+ if ((this->*creator)()) {
+ // add the generated package to package file names list
+ this->packageFileNames.emplace_back(
+ cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+ this->GetOption(output_var)));
+ return true;
+ }
+ return false;
+ };
+ bool retval =
+ make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME",
+ &cmCPackDebGenerator::createDeb);
+ cmValue dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR");
+ if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) {
+ retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME",
+ &cmCPackDebGenerator::createDbgsymDDeb) &&
+ retval;
+ }
+ return int(retval);
+}
+
+bool cmCPackDebGenerator::createDeb()
{
std::map<std::string, std::string> controlValues;
@@ -713,78 +718,77 @@ int cmCPackDebGenerator::createDeb()
controlValues["Package"] = cmsys::SystemTools::LowerCase(
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
controlValues["Version"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
controlValues["Section"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION");
controlValues["Priority"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY");
controlValues["Architecture"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
controlValues["Maintainer"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
controlValues["Description"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION");
- const char* debian_pkg_source =
+ cmValue debian_pkg_source =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
if (cmNonempty(debian_pkg_source)) {
- controlValues["Source"] = debian_pkg_source;
+ controlValues["Source"] = *debian_pkg_source;
}
- const char* debian_pkg_dep =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
+ cmValue debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS");
if (cmNonempty(debian_pkg_dep)) {
- controlValues["Depends"] = debian_pkg_dep;
+ controlValues["Depends"] = *debian_pkg_dep;
}
- const char* debian_pkg_rec =
+ cmValue debian_pkg_rec =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS");
if (cmNonempty(debian_pkg_rec)) {
- controlValues["Recommends"] = debian_pkg_rec;
+ controlValues["Recommends"] = *debian_pkg_rec;
}
- const char* debian_pkg_sug =
+ cmValue debian_pkg_sug =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
if (cmNonempty(debian_pkg_sug)) {
- controlValues["Suggests"] = debian_pkg_sug;
+ controlValues["Suggests"] = *debian_pkg_sug;
}
- const char* debian_pkg_url =
+ cmValue debian_pkg_url =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
if (cmNonempty(debian_pkg_url)) {
- controlValues["Homepage"] = debian_pkg_url;
+ controlValues["Homepage"] = *debian_pkg_url;
}
- const char* debian_pkg_predep =
+ cmValue debian_pkg_predep =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS");
if (cmNonempty(debian_pkg_predep)) {
- controlValues["Pre-Depends"] = debian_pkg_predep;
+ controlValues["Pre-Depends"] = *debian_pkg_predep;
}
- const char* debian_pkg_enhances =
+ cmValue debian_pkg_enhances =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES");
if (cmNonempty(debian_pkg_enhances)) {
- controlValues["Enhances"] = debian_pkg_enhances;
+ controlValues["Enhances"] = *debian_pkg_enhances;
}
- const char* debian_pkg_breaks =
+ cmValue debian_pkg_breaks =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS");
if (cmNonempty(debian_pkg_breaks)) {
- controlValues["Breaks"] = debian_pkg_breaks;
+ controlValues["Breaks"] = *debian_pkg_breaks;
}
- const char* debian_pkg_conflicts =
+ cmValue debian_pkg_conflicts =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS");
if (cmNonempty(debian_pkg_conflicts)) {
- controlValues["Conflicts"] = debian_pkg_conflicts;
+ controlValues["Conflicts"] = *debian_pkg_conflicts;
}
- const char* debian_pkg_provides =
+ cmValue debian_pkg_provides =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES");
if (cmNonempty(debian_pkg_provides)) {
- controlValues["Provides"] = debian_pkg_provides;
+ controlValues["Provides"] = *debian_pkg_provides;
}
- const char* debian_pkg_replaces =
+ cmValue debian_pkg_replaces =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES");
if (cmNonempty(debian_pkg_replaces)) {
- controlValues["Replaces"] = debian_pkg_replaces;
+ controlValues["Replaces"] = *debian_pkg_replaces;
}
const std::string strGenWDIR(this->GetOption("GEN_WDIR"));
const std::string shlibsfilename = strGenWDIR + "/shlibs";
- const char* debian_pkg_shlibs =
+ cmValue debian_pkg_shlibs =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS");
const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") &&
cmNonempty(debian_pkg_shlibs);
@@ -829,13 +833,10 @@ int cmCPackDebGenerator::createDeb()
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
- if (!gen.generate()) {
- return 0;
- }
- return 1;
+ return gen.generate();
}
-int cmCPackDebGenerator::createDbgsymDDeb()
+bool cmCPackDebGenerator::createDbgsymDDeb()
{
// Packages containing debug symbols follow the same structure as .debs
// but have different metadata and content.
@@ -844,38 +845,38 @@ int cmCPackDebGenerator::createDbgsymDDeb()
// debian policy enforce lower case for package name
std::string packageNameLower = cmsys::SystemTools::LowerCase(
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME"));
- const char* debian_pkg_version =
+ cmValue debian_pkg_version =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION");
controlValues["Package"] = packageNameLower + "-dbgsym";
controlValues["Package-Type"] = "ddeb";
- controlValues["Version"] = debian_pkg_version;
+ controlValues["Version"] = *debian_pkg_version;
controlValues["Auto-Built-Package"] = "debug-symbols";
- controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") +
- std::string(" (= ") + debian_pkg_version + ")";
+ controlValues["Depends"] =
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + std::string(" (= ") +
+ *debian_pkg_version + ")";
controlValues["Section"] = "debug";
controlValues["Priority"] = "optional";
controlValues["Architecture"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE");
controlValues["Maintainer"] =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
+ *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER");
controlValues["Description"] =
std::string("debug symbols for ") + packageNameLower;
- const char* debian_pkg_source =
+ cmValue debian_pkg_source =
this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE");
if (cmNonempty(debian_pkg_source)) {
- controlValues["Source"] = debian_pkg_source;
+ controlValues["Source"] = *debian_pkg_source;
}
- const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS");
+ cmValue debian_build_ids = this->GetOption("GEN_BUILD_IDS");
if (cmNonempty(debian_build_ids)) {
- controlValues["Build-Ids"] = debian_build_ids;
+ controlValues["Build-Ids"] = *debian_build_ids;
}
DebGenerator gen(
this->Logger, this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"),
this->GetOption("GEN_DBGSYMDIR"),
-
this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
this->GetOption("CPACK_TEMPORARY_DIRECTORY"),
this->GetOption("GEN_CPACK_DEBIAN_COMPRESSION_TYPE"),
@@ -885,10 +886,7 @@ int cmCPackDebGenerator::createDbgsymDDeb()
this->IsSet("GEN_CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION"),
this->packageFiles);
- if (!gen.generate()) {
- return 0;
- }
- return 1;
+ return gen.generate();
}
bool cmCPackDebGenerator::SupportsComponentInstallation() const
@@ -911,7 +909,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix(
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
if (nullptr != this->GetOption(groupVar)) {
- return std::string(this->GetOption(groupVar));
+ return *this->GetOption(groupVar);
}
return componentName;
}
diff --git a/Source/CPack/cmCPackDebGenerator.h b/Source/CPack/cmCPackDebGenerator.h
index ee8f39af6..61a6616d3 100644
--- a/Source/CPack/cmCPackDebGenerator.h
+++ b/Source/CPack/cmCPackDebGenerator.h
@@ -63,8 +63,9 @@ protected:
const std::string& componentName) override;
private:
- int createDeb();
- int createDbgsymDDeb();
+ bool createDebPackages();
+ bool createDeb();
+ bool createDbgsymDDeb();
std::vector<std::string> packageFiles;
};
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index b71c96982..9385a5a3e 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -20,6 +20,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
#ifdef HAVE_CoreServices
@@ -76,7 +77,7 @@ int cmCPackDragNDropGenerator::InitializeInternal()
"Cannot locate hdiutil command" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path);
const std::string setfile_path =
cmSystemTools::FindProgram("SetFile", paths, false);
@@ -85,7 +86,7 @@ int cmCPackDragNDropGenerator::InitializeInternal()
"Cannot locate SetFile command" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path);
const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false);
if (rez_path.empty()) {
@@ -93,7 +94,7 @@ int cmCPackDragNDropGenerator::InitializeInternal()
"Cannot locate Rez command" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path);
if (this->IsSet("CPACK_DMG_SLA_DIR")) {
slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR");
@@ -260,48 +261,35 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
const std::string& output_file)
{
// Get optional arguments ...
- const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON")
- ? this->GetOption("CPACK_PACKAGE_ICON")
- : "";
+ cmValue cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON");
const std::string cpack_dmg_volume_name =
this->GetOption("CPACK_DMG_VOLUME_NAME")
- ? this->GetOption("CPACK_DMG_VOLUME_NAME")
- : this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ ? *this->GetOption("CPACK_DMG_VOLUME_NAME")
+ : *this->GetOption("CPACK_PACKAGE_FILE_NAME");
const std::string cpack_dmg_format = this->GetOption("CPACK_DMG_FORMAT")
- ? this->GetOption("CPACK_DMG_FORMAT")
+ ? *this->GetOption("CPACK_DMG_FORMAT")
: "UDZO";
const std::string cpack_dmg_filesystem =
this->GetOption("CPACK_DMG_FILESYSTEM")
- ? this->GetOption("CPACK_DMG_FILESYSTEM")
+ ? *this->GetOption("CPACK_DMG_FILESYSTEM")
: "HFS+";
// Get optional arguments ...
std::string cpack_license_file =
- this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
- ? this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
- : "";
+ *this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
- const std::string cpack_dmg_background_image =
- this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
- ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
- : "";
+ cmValue cpack_dmg_background_image =
+ this->GetOption("CPACK_DMG_BACKGROUND_IMAGE");
- const std::string cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE")
- ? this->GetOption("CPACK_DMG_DS_STORE")
- : "";
+ cmValue cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE");
- const std::string cpack_dmg_languages =
- this->GetOption("CPACK_DMG_SLA_LANGUAGES")
- ? this->GetOption("CPACK_DMG_SLA_LANGUAGES")
- : "";
+ cmValue cpack_dmg_languages = this->GetOption("CPACK_DMG_SLA_LANGUAGES");
- const std::string cpack_dmg_ds_store_setup_script =
- this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
- ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
- : "";
+ cmValue cpack_dmg_ds_store_setup_script =
+ this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT");
const bool cpack_dmg_disable_applications_symlink =
this->IsOn("CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK");
@@ -332,7 +320,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
// Optionally add a custom volume icon ...
- if (!cpack_package_icon.empty()) {
+ if (!cpack_package_icon->empty()) {
std::ostringstream package_icon_source;
package_icon_source << cpack_package_icon;
@@ -351,7 +339,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
// Optionally add a custom .DS_Store file
// (e.g. for setting background/layout) ...
- if (!cpack_dmg_ds_store.empty()) {
+ if (!cpack_dmg_ds_store->empty()) {
std::ostringstream package_settings_source;
package_settings_source << cpack_dmg_ds_store;
@@ -372,7 +360,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
// Optionally add a custom background image ...
// Make sure the background file type is the same as the custom image
// and that the file is hidden so it doesn't show up.
- if (!cpack_dmg_background_image.empty()) {
+ if (!cpack_dmg_background_image->empty()) {
const std::string extension =
cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image);
std::ostringstream package_background_source;
@@ -394,7 +382,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
bool remount_image =
- !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty();
+ !cpack_package_icon->empty() || !cpack_dmg_ds_store_setup_script->empty();
std::string temp_image_format = "UDZO";
@@ -471,7 +459,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
}
// Optionally set the custom icon flag for the image ...
- if (!had_error && !cpack_package_icon.empty()) {
+ if (!had_error && !cpack_package_icon->empty()) {
std::string error;
std::ostringstream setfile_command;
setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
@@ -490,7 +478,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
// Optionally we can execute a custom apple script to generate
// the .DS_Store for the volume folder ...
- if (!had_error && !cpack_dmg_ds_store_setup_script.empty()) {
+ if (!had_error && !cpack_dmg_ds_store_setup_script->empty()) {
std::ostringstream setup_script_command;
setup_script_command << "osascript"
<< " \"" << cpack_dmg_ds_store_setup_script << "\""
@@ -718,7 +706,7 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
// the current COMPONENT belongs to.
std::string groupVar =
"CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
- const char* _groupName = GetOption(groupVar);
+ cmValue _groupName = this->GetOption(groupVar);
if (_groupName) {
std::string groupName = _groupName;
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
index e3521a0e5..157ee1de2 100644
--- a/Source/CPack/cmCPackExternalGenerator.cxx
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
int cmCPackExternalGenerator::InitializeInternal()
{
@@ -60,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles()
return 0;
}
- const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
+ cmValue packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
if (cmNonempty(packageScript)) {
if (!cmSystemTools::FileIsFullPath(packageScript)) {
cmCPackLogger(
@@ -76,10 +77,9 @@ int cmCPackExternalGenerator::PackageFiles()
return 0;
}
- const char* builtPackagesStr =
- this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES");
- if (builtPackagesStr) {
- cmExpandList(builtPackagesStr, this->packageFileNames, false);
+ cmValue builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES");
+ if (builtPackages) {
+ cmExpandList(builtPackages, this->packageFileNames, false);
}
}
@@ -181,43 +181,42 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON(
return 0;
}
- const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
+ cmValue packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
if (packageName) {
- root["packageName"] = packageName;
+ root["packageName"] = *packageName;
}
- const char* packageVersion =
- this->Parent->GetOption("CPACK_PACKAGE_VERSION");
+ cmValue packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION");
if (packageVersion) {
- root["packageVersion"] = packageVersion;
+ root["packageVersion"] = *packageVersion;
}
- const char* packageDescriptionFile =
+ cmValue packageDescriptionFile =
this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if (packageDescriptionFile) {
- root["packageDescriptionFile"] = packageDescriptionFile;
+ root["packageDescriptionFile"] = *packageDescriptionFile;
}
- const char* packageDescriptionSummary =
+ cmValue packageDescriptionSummary =
this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY");
if (packageDescriptionSummary) {
- root["packageDescriptionSummary"] = packageDescriptionSummary;
+ root["packageDescriptionSummary"] = *packageDescriptionSummary;
}
- const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
+ cmValue buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
if (buildConfigCstr) {
- root["buildConfig"] = buildConfigCstr;
+ root["buildConfig"] = *buildConfigCstr;
}
- const char* defaultDirectoryPermissions =
+ cmValue defaultDirectoryPermissions =
this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (cmNonempty(defaultDirectoryPermissions)) {
- root["defaultDirectoryPermissions"] = defaultDirectoryPermissions;
+ root["defaultDirectoryPermissions"] = *defaultDirectoryPermissions;
}
if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) {
root["setDestdir"] = true;
root["packagingInstallPrefix"] =
- this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ *this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
} else {
root["setDestdir"] = false;
}
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index b673006f2..30b6b0d7f 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -203,11 +203,11 @@ cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s,
// basically a wrapper that handles the NULL-ptr return from GetOption().
std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name)
{
- const char* pv = this->GetOption(var_name);
+ cmValue pv = this->GetOption(var_name);
if (!pv) {
return std::string();
}
- return pv;
+ return *pv;
}
// Produce UCL in the given @p manifest file for the common
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 00e274d6d..2f700b401 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -20,11 +20,11 @@
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmWorkingDirectory.h"
#include "cmXMLSafe.h"
@@ -78,14 +78,14 @@ int cmCPackGenerator::PrepareNames()
std::string tempDirectory =
cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/");
- const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
+ cmValue toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
if (toplevelTag) {
- tempDirectory += toplevelTag;
+ tempDirectory += *toplevelTag;
tempDirectory += "/";
}
- tempDirectory += this->GetOption("CPACK_GENERATOR");
+ tempDirectory += *this->GetOption("CPACK_GENERATOR");
std::string topDirectory = tempDirectory;
- const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ cmValue pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
if (!pfname) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_FILE_NAME not specified" << std::endl);
@@ -99,7 +99,7 @@ int cmCPackGenerator::PrepareNames()
return 0;
}
outName += this->GetOutputExtension();
- const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
+ cmValue pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY");
if (!pdir) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPACK_PACKAGE_DIRECTORY not specified" << std::endl);
@@ -107,25 +107,23 @@ int cmCPackGenerator::PrepareNames()
}
std::string destFile = pdir;
- this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile.c_str());
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PREFIX", destFile);
destFile += "/" + outName;
std::string outFile = topDirectory + "/" + outName;
- this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory.c_str());
- this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory.c_str());
- this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName.c_str());
- this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile.c_str());
- this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- outFile.c_str());
+ this->SetOptionIfNotSet("CPACK_TOPLEVEL_DIRECTORY", topDirectory);
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_DIRECTORY", tempDirectory);
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_NAME", outName);
+ this->SetOptionIfNotSet("CPACK_OUTPUT_FILE_PATH", destFile);
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_PACKAGE_FILE_NAME", outFile);
this->SetOptionIfNotSet("CPACK_INSTALL_DIRECTORY", this->GetInstallPath());
this->SetOptionIfNotSet(
"CPACK_NATIVE_INSTALL_DIRECTORY",
- cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()).c_str());
- this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY",
- tempDirectory.c_str());
+ cmsys::SystemTools::ConvertToOutputPath(this->GetInstallPath()));
+ this->SetOptionIfNotSet("CPACK_TEMPORARY_INSTALL_DIRECTORY", tempDirectory);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl);
- const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
+ cmValue descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Look for: " << descFileName << std::endl);
@@ -135,7 +133,7 @@ int cmCPackGenerator::PrepareNames()
<< descFileName << "]" << std::endl);
return 0;
}
- cmsys::ifstream ifs(descFileName);
+ cmsys::ifstream ifs(descFileName->c_str());
if (!ifs) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot open description file name: " << descFileName
@@ -150,10 +148,10 @@ int cmCPackGenerator::PrepareNames()
while (ifs && cmSystemTools::GetLineFromStream(ifs, line)) {
ostr << cmXMLSafe(line) << std::endl;
}
- this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str());
- const char* defFileName =
+ this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str());
+ cmValue defFileName =
this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE");
- if (defFileName && !strcmp(defFileName, descFileName)) {
+ if (defFileName && (defFileName == descFileName)) {
this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON");
}
}
@@ -165,9 +163,9 @@ int cmCPackGenerator::PrepareNames()
<< std::endl);
return 0;
}
- const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+ cmValue algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM");
if (algoSignature) {
- if (!cmCryptoHash::New(algoSignature)) {
+ if (!cmCryptoHash::New(*algoSignature)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Cannot recognize algorithm: " << algoSignature
<< std::endl);
@@ -215,7 +213,7 @@ int cmCPackGenerator::InstallProject()
// prepare default created directory permissions
mode_t default_dir_mode_v = 0;
mode_t* default_dir_mode = nullptr;
- const char* default_dir_install_permissions =
+ cmValue default_dir_install_permissions =
this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (cmNonempty(default_dir_install_permissions)) {
std::vector<std::string> items =
@@ -266,7 +264,7 @@ int cmCPackGenerator::InstallProject()
}
// Run pre-build actions
- const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS");
+ cmValue preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS");
if (preBuildScripts) {
const auto scripts = cmExpandedList(preBuildScripts, false);
for (const auto& script : scripts) {
@@ -293,7 +291,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
bool setDestDir, const std::string& tempInstallDirectory)
{
(void)setDestDir;
- const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
+ cmValue installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
if (cmNonempty(installCommands)) {
std::string tempInstallDirectoryEnv =
cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
@@ -333,7 +331,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
(void)setDestDir;
(void)tempInstallDirectory;
std::vector<cmsys::RegularExpression> ignoreFilesRegex;
- const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
+ cmValue cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES");
if (cpackIgnoreFiles) {
std::vector<std::string> ignoreFilesRegexString =
cmExpandedList(cpackIgnoreFiles);
@@ -343,8 +341,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
ignoreFilesRegex.emplace_back(ifr);
}
}
- const char* installDirectories =
- this->GetOption("CPACK_INSTALLED_DIRECTORIES");
+ cmValue installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES");
if (cmNonempty(installDirectories)) {
std::vector<std::string> installDirectoriesVector =
cmExpandedList(installDirectories);
@@ -472,9 +469,9 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
int cmCPackGenerator::InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory)
{
- const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
+ cmValue cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
{
- const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
+ cmValue const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
if (cmakeScript && cmakeScripts) {
cmCPackLogger(
cmCPackLog::LOG_WARNING,
@@ -485,7 +482,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
cmakeScripts = cmakeScript;
}
}
- if (cmakeScripts && *cmakeScripts) {
+ if (cmakeScripts && !cmakeScripts->empty()) {
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Install scripts: " << cmakeScripts << std::endl);
std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts);
@@ -502,9 +499,9 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
std::string dir;
if (this->GetOption("CPACK_INSTALL_PREFIX")) {
- dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ dir += *this->GetOption("CPACK_INSTALL_PREFIX");
}
- this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str());
+ this->SetOption("CMAKE_INSTALL_PREFIX", dir);
cmCPackLogger(
cmCPackLog::LOG_DEBUG,
"- Using DESTDIR + CPACK_INSTALL_PREFIX... (this->SetOption)"
@@ -513,7 +510,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
"- Setting CMAKE_INSTALL_PREFIX to '" << dir << "'"
<< std::endl);
} else {
- this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str());
+ this->SetOption("CMAKE_INSTALL_PREFIX", tempInstallDirectory);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"- Using non-DESTDIR install... (this->SetOption)"
@@ -524,9 +521,9 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
}
this->SetOptionIfNotSet("CMAKE_CURRENT_BINARY_DIR",
- tempInstallDirectory.c_str());
+ tempInstallDirectory);
this->SetOptionIfNotSet("CMAKE_CURRENT_SOURCE_DIR",
- tempInstallDirectory.c_str());
+ tempInstallDirectory);
bool res = this->MakefileMap->ReadListFile(installScript);
if (cmSystemTools::GetErrorOccuredFlag() || !res) {
return 0;
@@ -540,8 +537,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
bool setDestDir, const std::string& baseTempInstallDirectory,
const mode_t* default_dir_mode)
{
- const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
- const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
+ cmValue cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
+ cmValue cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
std::string absoluteDestFiles;
if (cmNonempty(cmakeProjects)) {
if (!cmakeGenerator) {
@@ -595,7 +592,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// Determine the installation types for this project (if provided).
std::string installTypesVar = "CPACK_" +
cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES";
- const char* installTypes = this->GetOption(installTypesVar);
+ cmValue installTypes = this->GetOption(installTypesVar);
if (cmNonempty(installTypes)) {
std::vector<std::string> installTypesVector =
cmExpandedList(installTypes);
@@ -608,7 +605,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// Determine the set of components that will be used in this project
std::string componentsVar =
"CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component);
- const char* components = this->GetOption(componentsVar);
+ cmValue components = this->GetOption(componentsVar);
if (cmNonempty(components)) {
cmExpandList(components, componentsVector);
for (std::string const& comp : componentsVector) {
@@ -625,12 +622,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
std::vector<std::string> buildConfigs;
// Try get configuration names given via `-C` CLI option
- {
- const char* const buildConfigCstr =
- this->GetOption("CPACK_BUILD_CONFIG");
- auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{};
- cmExpandList(buildConfig, buildConfigs);
- }
+ cmExpandList(this->GetOption("CPACK_BUILD_CONFIG"), buildConfigs);
// Remove duplicates
std::sort(buildConfigs.begin(), buildConfigs.end());
@@ -682,8 +674,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
this->CMakeProjects.emplace_back(std::move(project));
}
}
- this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
- absoluteDestFiles.c_str());
+ this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES", absoluteDestFiles);
return 1;
}
@@ -767,11 +758,11 @@ int cmCPackGenerator::InstallCMakeProject(
tempInstallDirectory += this->GetComponentInstallDirNameSuffix(component);
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
tempInstallDirectory += "/";
- tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+ tempInstallDirectory += *this->GetOption("CPACK_PACKAGE_FILE_NAME");
}
}
- const char* default_dir_inst_permissions =
+ cmValue default_dir_inst_permissions =
this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (cmNonempty(default_dir_inst_permissions)) {
mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
@@ -800,7 +791,7 @@ int cmCPackGenerator::InstallCMakeProject(
}
std::string dir;
if (this->GetOption("CPACK_INSTALL_PREFIX")) {
- dir += this->GetOption("CPACK_INSTALL_PREFIX");
+ dir += *this->GetOption("CPACK_INSTALL_PREFIX");
}
mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir);
@@ -924,7 +915,7 @@ int cmCPackGenerator::InstallCMakeProject(
// forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES
// to CPack (may be used by generators like CPack RPM or DEB)
// in order to transparently handle ABSOLUTE PATH
- if (cmProp def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
+ if (cmValue def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) {
mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", *def);
}
@@ -958,7 +949,7 @@ int cmCPackGenerator::InstallCMakeProject(
}
}
- if (cmProp d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
+ if (cmValue d = mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")) {
if (!absoluteDestFiles.empty()) {
absoluteDestFiles += ";";
}
@@ -975,11 +966,10 @@ int cmCPackGenerator::InstallCMakeProject(
std::string absoluteDestFilesListComponent =
cmStrCat(this->GetOption(absoluteDestFileComponent), ';', *d);
this->SetOption(absoluteDestFileComponent,
- absoluteDestFilesListComponent.c_str());
+ absoluteDestFilesListComponent);
} else {
- this->SetOption(
- absoluteDestFileComponent,
- cmToCStr(mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")));
+ this->SetOption(absoluteDestFileComponent,
+ mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
}
}
}
@@ -999,17 +989,29 @@ bool cmCPackGenerator::ReadListFile(const char* moduleName)
return retval;
}
-void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
- const char* value)
+template <typename ValueType>
+void cmCPackGenerator::StoreOptionIfNotSet(const std::string& op,
+ ValueType value)
{
- cmProp def = this->MakefileMap->GetDefinition(op);
+ cmValue def = this->MakefileMap->GetDefinition(op);
if (cmNonempty(def)) {
return;
}
- this->SetOption(op, value);
+ this->StoreOption(op, value);
}
-void cmCPackGenerator::SetOption(const std::string& op, const char* value)
+void cmCPackGenerator::SetOptionIfNotSet(const std::string& op,
+ const char* value)
+{
+ this->StoreOptionIfNotSet(op, value);
+}
+void cmCPackGenerator::SetOptionIfNotSet(const std::string& op, cmValue value)
+{
+ this->StoreOptionIfNotSet(op, value);
+}
+
+template <typename ValueType>
+void cmCPackGenerator::StoreOption(const std::string& op, ValueType value)
{
if (!value) {
this->MakefileMap->RemoveDefinition(op);
@@ -1021,6 +1023,15 @@ void cmCPackGenerator::SetOption(const std::string& op, const char* value)
this->MakefileMap->AddDefinition(op, value);
}
+void cmCPackGenerator::SetOption(const std::string& op, const char* value)
+{
+ this->StoreOption(op, value);
+}
+void cmCPackGenerator::SetOption(const std::string& op, cmValue value)
+{
+ this->StoreOption(op, value);
+}
+
int cmCPackGenerator::DoPackage()
{
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
@@ -1038,8 +1049,7 @@ int cmCPackGenerator::DoPackage()
}
if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) {
- const char* toplevelDirectory =
- this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ cmValue toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
if (cmSystemTools::FileExists(toplevelDirectory)) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Remove toplevel directory: " << toplevelDirectory
@@ -1060,9 +1070,9 @@ int cmCPackGenerator::DoPackage()
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl);
- const char* tempPackageFileName =
+ cmValue tempPackageFileName =
this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
- const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ cmValue tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
cmsys::Glob gl;
@@ -1079,7 +1089,7 @@ int cmCPackGenerator::DoPackage()
cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl);
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Package files to: "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << (tempPackageFileName ? *tempPackageFileName : "(NULL)")
<< std::endl);
if (cmSystemTools::FileExists(tempPackageFileName)) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
@@ -1099,9 +1109,8 @@ int cmCPackGenerator::DoPackage()
* may update this during PackageFiles.
* (either putting several names or updating the provided one)
*/
- this->packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName
- : "");
- this->toplevel = tempDirectory;
+ this->packageFileNames.emplace_back(tempPackageFileName);
+ this->toplevel = *tempDirectory;
{ // scope that enables package generators to run internal scripts with
// latest CMake policies enabled
cmMakefile::ScopePushPop pp{ this->MakefileMap };
@@ -1115,7 +1124,7 @@ int cmCPackGenerator::DoPackage()
}
}
// Run post-build actions
- const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS");
+ cmValue postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS");
if (postBuildScripts) {
this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES",
cmJoin(this->packageFileNames, ";"));
@@ -1135,8 +1144,8 @@ int cmCPackGenerator::DoPackage()
}
/* Prepare checksum algorithm*/
- const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
- std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : "");
+ cmValue algo = this->GetOption("CPACK_PACKAGE_CHECKSUM");
+ std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(*algo);
/*
* Copy the generated packages to final destination
@@ -1151,19 +1160,19 @@ int cmCPackGenerator::DoPackage()
for (std::string const& pkgFileName : this->packageFileNames) {
std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX"));
std::string filename(cmSystemTools::GetFilenameName(pkgFileName));
- tempPackageFileName = pkgFileName.c_str();
+ tempPackageFileName = cmValue(pkgFileName);
tmpPF += "/" + filename;
const char* packageFileName = tmpPF.c_str();
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Copy final package(s): "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)")
+ << (tempPackageFileName ? *tempPackageFileName : "(NULL)")
<< " to " << (packageFileName ? packageFileName : "(NULL)")
<< std::endl);
if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
"Problem copying the package: "
- << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to "
+ << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << " to "
<< (packageFileName ? packageFileName : "(NULL)") << std::endl);
return 0;
}
@@ -1198,9 +1207,9 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf)
this->MakefileMap = mf;
this->Name = name;
// set the running generator name
- this->SetOption("CPACK_GENERATOR", this->Name.c_str());
+ this->SetOption("CPACK_GENERATOR", this->Name);
// Load the project specific config file
- const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
+ cmValue config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
if (config) {
mf->ReadListFile(config);
}
@@ -1234,7 +1243,7 @@ bool cmCPackGenerator::IsOn(const std::string& name) const
bool cmCPackGenerator::IsSetToOff(const std::string& op) const
{
- cmProp ret = this->MakefileMap->GetDefinition(op);
+ cmValue ret = this->MakefileMap->GetDefinition(op);
if (cmNonempty(ret)) {
return cmIsOff(*ret);
}
@@ -1243,22 +1252,21 @@ bool cmCPackGenerator::IsSetToOff(const std::string& op) const
bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const
{
- cmProp ret = this->MakefileMap->GetDefinition(op);
+ cmValue ret = this->MakefileMap->GetDefinition(op);
if (ret) {
return ret->empty();
}
return false;
}
-const char* cmCPackGenerator::GetOption(const std::string& op) const
+cmValue cmCPackGenerator::GetOption(const std::string& op) const
{
- cmProp ret = this->MakefileMap->GetDefinition(op);
+ cmValue ret = this->MakefileMap->GetDefinition(op);
if (!ret) {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Warning, GetOption return NULL for: " << op << std::endl);
- return nullptr;
}
- return ret->c_str();
+ return ret;
}
std::vector<std::string> cmCPackGenerator::GetOptions() const
@@ -1311,7 +1319,7 @@ const char* cmCPackGenerator::GetPackagingInstallPrefix()
<< this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'"
<< std::endl);
- return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+ return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")->c_str();
}
std::string cmCPackGenerator::FindTemplate(const char* name)
@@ -1391,12 +1399,8 @@ int cmCPackGenerator::PrepareGroupingKind()
method = ONE_PACKAGE_PER_GROUP;
}
- std::string groupingType;
-
// Second way to specify grouping
- if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) {
- groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING");
- }
+ std::string groupingType = *this->GetOption("CPACK_COMPONENTS_GROUPING");
if (!groupingType.empty()) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
@@ -1477,18 +1481,18 @@ std::string cmCPackGenerator::GetComponentPackageFileName(
if (isGroupName) {
std::string groupDispVar = "CPACK_COMPONENT_GROUP_" +
cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* groupDispName = this->GetOption(groupDispVar);
+ cmValue groupDispName = this->GetOption(groupDispVar);
if (groupDispName) {
- suffix = "-" + std::string(groupDispName);
+ suffix = "-" + *groupDispName;
}
}
/* the [single] component case */
else {
std::string dispVar = "CPACK_COMPONENT_" +
cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME";
- const char* dispName = this->GetOption(dispVar);
+ cmValue dispName = this->GetOption(dispVar);
if (dispName) {
- suffix = "-" + std::string(dispName);
+ suffix = "-" + *dispName;
}
}
}
@@ -1531,9 +1535,9 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType(
"CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name);
installType->Name = name;
- const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
if (cmNonempty(displayName)) {
- installType->DisplayName = displayName;
+ installType->DisplayName = *displayName;
} else {
installType->DisplayName = installType->Name;
}
@@ -1553,9 +1557,9 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
std::string macroPrefix =
"CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name);
component->Name = name;
- const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
if (cmNonempty(displayName)) {
- component->DisplayName = displayName;
+ component->DisplayName = *displayName;
} else {
component->DisplayName = component->Name;
}
@@ -1565,17 +1569,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") ||
cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL"));
- const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
+ cmValue archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
if (cmNonempty(archiveFile)) {
- component->ArchiveFile = archiveFile;
+ component->ArchiveFile = *archiveFile;
}
- const char* plist = this->GetOption(macroPrefix + "_PLIST");
+ cmValue plist = this->GetOption(macroPrefix + "_PLIST");
if (cmNonempty(plist)) {
- component->Plist = plist;
+ component->Plist = *plist;
}
- const char* groupName = this->GetOption(macroPrefix + "_GROUP");
+ cmValue groupName = this->GetOption(macroPrefix + "_GROUP");
if (cmNonempty(groupName)) {
component->Group = this->GetComponentGroup(projectName, groupName);
component->Group->Components.push_back(component);
@@ -1583,13 +1587,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
component->Group = nullptr;
}
- const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ cmValue description = this->GetOption(macroPrefix + "_DESCRIPTION");
if (cmNonempty(description)) {
- component->Description = description;
+ component->Description = *description;
}
// Determine the installation types.
- const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
+ cmValue installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES");
if (cmNonempty(installTypes)) {
std::vector<std::string> installTypesVector =
cmExpandedList(installTypes);
@@ -1600,7 +1604,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent(
}
// Determine the component dependencies.
- const char* depends = this->GetOption(macroPrefix + "_DEPENDS");
+ cmValue depends = this->GetOption(macroPrefix + "_DEPENDS");
if (cmNonempty(depends)) {
std::vector<std::string> dependsVector = cmExpandedList(depends);
for (std::string const& depend : dependsVector) {
@@ -1624,21 +1628,20 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup(
if (!hasGroup) {
// Define the group
group->Name = name;
- const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
+ cmValue displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME");
if (cmNonempty(displayName)) {
- group->DisplayName = displayName;
+ group->DisplayName = *displayName;
} else {
group->DisplayName = group->Name;
}
- const char* description = this->GetOption(macroPrefix + "_DESCRIPTION");
+ cmValue description = this->GetOption(macroPrefix + "_DESCRIPTION");
if (cmNonempty(description)) {
- group->Description = description;
+ group->Description = *description;
}
group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE");
group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED");
- const char* parentGroupName =
- this->GetOption(macroPrefix + "_PARENT_GROUP");
+ cmValue parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP");
if (cmNonempty(parentGroupName)) {
group->ParentGroup =
this->GetComponentGroup(projectName, parentGroupName);
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 2512d4208..65156ab25 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -13,6 +13,7 @@
#include "cmCPackComponentGroup.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmCPackLog;
class cmGlobalGenerator;
@@ -84,8 +85,18 @@ public:
//! Set and get the options
void SetOption(const std::string& op, const char* value);
+ void SetOption(const std::string& op, const std::string& value)
+ {
+ this->SetOption(op, cmValue(value));
+ }
+ void SetOption(const std::string& op, cmValue value);
void SetOptionIfNotSet(const std::string& op, const char* value);
- const char* GetOption(const std::string& op) const;
+ void SetOptionIfNotSet(const std::string& op, const std::string& value)
+ {
+ this->SetOptionIfNotSet(op, cmValue(value));
+ }
+ void SetOptionIfNotSet(const std::string& op, cmValue value);
+ cmValue GetOption(const std::string& op) const;
std::vector<std::string> GetOptions() const;
bool IsSet(const std::string& name) const;
bool IsOn(const std::string& name) const;
@@ -323,6 +334,12 @@ protected:
bool TraceExpand;
cmMakefile* MakefileMap;
+
+private:
+ template <typename ValueType>
+ void StoreOption(const std::string& op, ValueType value);
+ template <typename ValueType>
+ void StoreOptionIfNotSet(const std::string& op, ValueType value);
};
#define cmCPackTypeMacro(klass, superclass) \
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 6bd0d1b2a..ecc5e0849 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
/* NSIS uses different command line syntax on Windows and others */
#ifdef _WIN32
@@ -84,7 +85,7 @@ int cmCPackNSISGenerator::PackageFiles()
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Uninstall Files: " << str.str() << std::endl);
- this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str().c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_DELETE_FILES", str.str());
std::vector<std::string> dirs;
this->GetListOfSubdirectories(this->toplevel.c_str(), dirs);
std::ostringstream dstr;
@@ -120,7 +121,7 @@ int cmCPackNSISGenerator::PackageFiles()
}
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"Uninstall Dirs: " << dstr.str() << std::endl);
- this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str().c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_DELETE_DIRECTORIES", dstr.str());
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Configure file: " << nsisInFileName << " to " << nsisFileName
@@ -142,15 +143,15 @@ int cmCPackNSISGenerator::PackageFiles()
}
std::string installerHeaderImage;
if (this->IsSet("CPACK_NSIS_MUI_HEADERIMAGE")) {
- installerHeaderImage = this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE");
+ installerHeaderImage = *this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE");
} else if (this->IsSet("CPACK_PACKAGE_ICON")) {
- installerHeaderImage = this->GetOption("CPACK_PACKAGE_ICON");
+ installerHeaderImage = *this->GetOption("CPACK_PACKAGE_ICON");
}
if (!installerHeaderImage.empty()) {
std::string installerIconCode = cmStrCat(
"!define MUI_HEADERIMAGE_BITMAP \"", installerHeaderImage, "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE",
- installerIconCode.c_str());
+ installerIconCode);
}
if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) {
@@ -158,7 +159,7 @@ int cmCPackNSISGenerator::PackageFiles()
"!define MUI_WELCOMEFINISHPAGE_BITMAP \"",
this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE",
- installerBitmapCode.c_str());
+ installerBitmapCode);
}
if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) {
@@ -166,7 +167,7 @@ int cmCPackNSISGenerator::PackageFiles()
"!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"",
this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE",
- installerBitmapCode.c_str());
+ installerBitmapCode);
}
if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) {
@@ -175,7 +176,7 @@ int cmCPackNSISGenerator::PackageFiles()
this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\',
this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE",
- installerRunCode.c_str());
+ installerRunCode);
}
if (this->IsSet("CPACK_NSIS_WELCOME_TITLE")) {
@@ -183,7 +184,7 @@ int cmCPackNSISGenerator::PackageFiles()
cmStrCat("!define MUI_WELCOMEPAGE_TITLE \"",
this->GetOption("CPACK_NSIS_WELCOME_TITLE"), "\"");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_WELCOME_TITLE_CODE",
- welcomeTitleCode.c_str());
+ welcomeTitleCode);
}
if (this->IsSet("CPACK_NSIS_WELCOME_TITLE_3LINES")) {
@@ -196,7 +197,7 @@ int cmCPackNSISGenerator::PackageFiles()
cmStrCat("!define MUI_FINISHPAGE_TITLE \"",
this->GetOption("CPACK_NSIS_FINISH_TITLE"), "\"");
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_FINISH_TITLE_CODE",
- finishTitleCode.c_str());
+ finishTitleCode);
}
if (this->IsSet("CPACK_NSIS_FINISH_TITLE_3LINES")) {
@@ -231,8 +232,14 @@ int cmCPackNSISGenerator::PackageFiles()
std::string brandingTextCode =
cmStrCat("BrandingText /TRIM", brandingTextPosition, " \"",
this->GetOption("CPACK_NSIS_BRANDING_TEXT"), "\"\n");
- this->SetOptionIfNotSet("CPACK_NSIS_BRANDING_TEXT_CODE",
- brandingTextCode.c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_BRANDING_TEXT_CODE", brandingTextCode);
+ }
+
+ if (!this->IsSet("CPACK_NSIS_IGNORE_LICENSE_PAGE")) {
+ std::string licenceCode =
+ cmStrCat("!insertmacro MUI_PAGE_LICENSE \"",
+ this->GetOption("CPACK_RESOURCE_FILE_LICENSE"), "\"\n");
+ this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode);
}
// Setup all of the component sections
@@ -327,7 +334,7 @@ int cmCPackNSISGenerator::PackageFiles()
componentDescriptions + groupDescriptions +
"!insertmacro MUI_FUNCTION_DESCRIPTION_END\n";
this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC",
- componentDescriptions.c_str());
+ componentDescriptions);
}
if (anyDownloadedComponents) {
@@ -337,18 +344,15 @@ int cmCPackNSISGenerator::PackageFiles()
}
}
- this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES",
- installTypesCode.c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", installTypesCode);
this->SetOptionIfNotSet("CPACK_NSIS_PAGE_COMPONENTS",
"!insertmacro MUI_PAGE_COMPONENTS");
this->SetOptionIfNotSet("CPACK_NSIS_FULL_INSTALL", "");
- this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS",
- componentCode.c_str());
- this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST",
- sectionList.c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTIONS", componentCode);
+ this->SetOptionIfNotSet("CPACK_NSIS_COMPONENT_SECTION_LIST", sectionList);
this->SetOptionIfNotSet("CPACK_NSIS_SECTION_SELECTED_VARS",
- selectedVarsList.c_str());
- this->SetOption("CPACK_NSIS_DEFINES", defines.c_str());
+ selectedVarsList);
+ this->SetOption("CPACK_NSIS_DEFINES", defines);
}
this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions);
@@ -472,8 +476,8 @@ int cmCPackNSISGenerator::InitializeInternal()
cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
if (!resS || retVal ||
(!versionRex.find(output) && !versionRexCVS.find(output))) {
- const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
- std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log");
+ cmValue topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ std::string tmpFile = cmStrCat(topDir ? *topDir : ".", "/NSISOutput.log");
cmGeneratedFileStream ofs(tmpFile);
ofs << "# Run command: " << nsisCmd << std::endl
<< "# Output:" << std::endl
@@ -487,12 +491,12 @@ int cmCPackNSISGenerator::InitializeInternal()
}
if (versionRex.find(output)) {
double nsisVersion = atof(versionRex.match(1).c_str());
- double minNSISVersion = 3.0;
+ double minNSISVersion = 3.03;
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"NSIS Version: " << nsisVersion << std::endl);
if (nsisVersion < minNSISVersion) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack requires NSIS Version 3.0 or greater. "
+ "CPack requires NSIS Version 3.03 or greater. "
"NSIS found on the system was: "
<< nsisVersion << std::endl);
return 0;
@@ -503,13 +507,13 @@ int cmCPackNSISGenerator::InitializeInternal()
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"NSIS Version: CVS " << versionRexCVS.match(1) << std::endl);
}
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath);
this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin");
- const char* cpackPackageExecutables =
+ cmValue cpackPackageExecutables =
this->GetOption("CPACK_PACKAGE_EXECUTABLES");
- const char* cpackPackageDeskTopLinks =
+ cmValue cpackPackageDeskTopLinks =
this->GetOption("CPACK_CREATE_DESKTOP_LINKS");
- const char* cpackNsisExecutablesDirectory =
+ cmValue cpackNsisExecutablesDirectory =
this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
std::vector<std::string> cpackPackageDesktopLinksVector;
if (cpackPackageDeskTopLinks) {
@@ -571,8 +575,8 @@ int cmCPackNSISGenerator::InitializeInternal()
}
this->CreateMenuLinks(str, deleteStr);
- this->SetOptionIfNotSet("CPACK_NSIS_CREATE_ICONS", str.str().c_str());
- this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS", deleteStr.str().c_str());
+ this->SetOptionIfNotSet("CPACK_NSIS_CREATE_ICONS", str.str());
+ this->SetOptionIfNotSet("CPACK_NSIS_DELETE_ICONS", deleteStr.str());
this->SetOptionIfNotSet("CPACK_NSIS_COMPRESSOR", "lzma");
@@ -582,7 +586,7 @@ int cmCPackNSISGenerator::InitializeInternal()
void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
std::ostream& deleteStr)
{
- const char* cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS");
+ cmValue cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS");
if (!cpackMenuLinks) {
return;
}
@@ -721,11 +725,10 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
}
// Create the directory for the upload area
- const char* userUploadDirectory =
- this->GetOption("CPACK_UPLOAD_DIRECTORY");
+ cmValue userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY");
std::string uploadDirectory;
if (cmNonempty(userUploadDirectory)) {
- uploadDirectory = userUploadDirectory;
+ uploadDirectory = *userUploadDirectory;
} else {
uploadDirectory =
cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
@@ -961,9 +964,9 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription(
std::string cmCPackNSISGenerator::CustomComponentInstallDirectory(
cm::string_view componentName)
{
- const char* outputDir = this->GetOption(
+ cmValue outputDir = this->GetOption(
cmStrCat("CPACK_NSIS_", componentName, "_INSTALL_DIRECTORY"));
- return outputDir ? outputDir : "$INSTDIR";
+ return outputDir ? *outputDir : "$INSTDIR";
}
std::string cmCPackNSISGenerator::TranslateNewlines(std::string str)
diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx
index 98dc8906f..5de817937 100644
--- a/Source/CPack/cmCPackNuGetGenerator.cxx
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmCPackLog.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
bool cmCPackNuGetGenerator::SupportsComponentInstallation() const
{
@@ -81,10 +82,10 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
std::back_inserter(components),
[](cmCPackComponent const* comp) { return comp->Name; });
this->SetOption("CPACK_NUGET_" + compGUp + "_GROUP_COMPONENTS",
- cmJoin(components, ";").c_str());
+ cmJoin(components, ";"));
}
if (!groups.empty()) {
- this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";").c_str());
+ this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";"));
}
// Handle Orphan components (components not belonging to any groups)
@@ -102,8 +103,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
}
}
if (!components.empty()) {
- this->SetOption("CPACK_NUGET_COMPONENTS",
- cmJoin(components, ";").c_str());
+ this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";"));
}
} else {
@@ -114,13 +114,13 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
[](std::pair<std::string, cmCPackComponent> const& comp) {
return comp.first;
});
- this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";").c_str());
+ this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";"));
}
}
void cmCPackNuGetGenerator::AddGeneratedPackageNames()
{
- const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES");
+ cmValue const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES");
if (!files_list) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
@@ -129,7 +129,7 @@ void cmCPackNuGetGenerator::AddGeneratedPackageNames()
return;
}
// add the generated packages to package file names list
- std::string fileNames{ files_list };
+ const std::string& fileNames = *files_list;
const char sep = ';';
std::string::size_type pos1 = 0;
std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 5de4a6f3f..7bf1dc735 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -12,6 +12,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackOSXX11Generator::cmCPackOSXX11Generator() = default;
@@ -22,7 +23,7 @@ int cmCPackOSXX11Generator::PackageFiles()
// TODO: Use toplevel ?
// It is used! Is this an obsolete comment?
- const char* cpackPackageExecutables =
+ cmValue cpackPackageExecutables =
this->GetOption("CPACK_PACKAGE_EXECUTABLES");
if (cpackPackageExecutables) {
cmCPackLogger(cmCPackLog::LOG_DEBUG,
@@ -45,8 +46,7 @@ int cmCPackOSXX11Generator::PackageFiles()
it != cpackPackageExecutablesVector.end(); ++it) {
std::string cpackExecutableName = *it;
++it;
- this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME",
- cpackExecutableName.c_str());
+ this->SetOptionIfNotSet("CPACK_EXECUTABLE_NAME", cpackExecutableName);
}
}
@@ -70,7 +70,7 @@ int cmCPackOSXX11Generator::PackageFiles()
const char* scrDir = scriptDirectory.c_str();
const char* contDir = contentsDirectory.c_str();
const char* rsrcFile = resourceFileName.c_str();
- const char* iconFile = this->GetOption("CPACK_PACKAGE_ICON");
+ cmValue iconFile = this->GetOption("CPACK_PACKAGE_ICON");
if (iconFile) {
std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile);
if (!cmSystemTools::FileExists(iconFile)) {
@@ -83,7 +83,7 @@ int cmCPackOSXX11Generator::PackageFiles()
}
std::string destFileName = resourcesDirectory + "/" + iconFileName;
this->ConfigureFile(iconFile, destFileName, true);
- this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName.c_str());
+ this->SetOptionIfNotSet("CPACK_APPLE_GUI_ICON", iconFileName);
}
std::string applicationsLinkName = diskImageDirectory + "/Applications";
@@ -103,9 +103,9 @@ int cmCPackOSXX11Generator::PackageFiles()
true) ||
!this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir, rsrcFile,
true) ||
- !this->CopyResourcePlistFile("OSXScriptLauncher", appdir,
- this->GetOption("CPACK_PACKAGE_FILE_NAME"),
- true)) {
+ !this->CopyResourcePlistFile(
+ "OSXScriptLauncher", appdir,
+ this->GetOption("CPACK_PACKAGE_FILE_NAME").GetCStr(), true)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem copying the resource files" << std::endl);
return 0;
@@ -190,8 +190,7 @@ int cmCPackOSXX11Generator::InitializeInternal()
"Cannot find hdiutil compiler" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
- pkgPath.c_str());
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath);
return this->Superclass::InitializeInternal();
}
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index ac3d64d9a..91adf321e 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmCPackLog.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
cmCPackPKGGenerator::cmCPackPKGGenerator()
@@ -56,7 +57,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName,
std::string opt = (themeName == nullptr)
? cmStrCat("CPACK_", genName, "_BACKGROUND")
: cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix);
- const char* bgFileName = this->GetOption(opt);
+ cmValue bgFileName = this->GetOption(opt);
if (bgFileName == nullptr) {
return;
}
@@ -78,7 +79,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName,
xout.Attribute("file", bgFileName);
- const char* param = this->GetOption(cmStrCat(opt, "_ALIGNMENT"));
+ cmValue param = this->GetOption(cmStrCat(opt, "_ALIGNMENT"));
if (param != nullptr) {
xout.Attribute("alignment", param);
}
@@ -166,7 +167,7 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
// Dark Aqua
this->CreateBackground("darkAqua", metapackageFile, genName, xout);
- this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str());
+ this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str());
// Create the distribution.dist file in the metapackage to turn it
// into a distribution package.
@@ -315,7 +316,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
{
std::string uname = cmSystemTools::UpperCase(name);
std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname;
- const char* inFileName = this->GetOption(cpackVar);
+ cmValue inFileName = this->GetOption(cpackVar);
if (!inFileName) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"CPack option: " << cpackVar.c_str()
@@ -347,11 +348,10 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
// Set this so that distribution.dist gets the right name (without
// the path).
- this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH",
- (name + ext).c_str());
+ this->SetOption("CPACK_RESOURCE_FILE_" + uname + "_NOPATH", (name + ext));
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
- "Configure file: " << (inFileName ? inFileName : "(NULL)")
+ "Configure file: " << (inFileName ? *inFileName : "(NULL)")
<< " to " << destFileName << std::endl);
this->ConfigureFile(inFileName, destFileName);
return true;
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index f51ea42de..a8cf1fad9 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
static inline unsigned int getVersion(unsigned int major, unsigned int minor)
@@ -79,9 +80,9 @@ int cmCPackPackageMakerGenerator::PackageFiles()
resDir += "/en.lproj";
}
- const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
- const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
- const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT");
+ cmValue preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
+ cmValue postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
+ cmValue postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT");
if (this->Components.empty()) {
// Create directory structure
@@ -167,10 +168,9 @@ int cmCPackPackageMakerGenerator::PackageFiles()
// Create the directory where downloaded component packages will
// be placed.
- const char* userUploadDirectory =
- this->GetOption("CPACK_UPLOAD_DIRECTORY");
+ cmValue userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY");
std::string uploadDirectory;
- if (userUploadDirectory && *userUploadDirectory) {
+ if (userUploadDirectory && !userUploadDirectory->empty()) {
uploadDirectory = userUploadDirectory;
} else {
uploadDirectory =
@@ -352,8 +352,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
"/PackageMaker.app/Contents/MacOS");
std::string pkgPath;
- const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
- if (inst_program && *inst_program) {
+ cmValue inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
+ if (inst_program && !inst_program->empty()) {
pkgPath = inst_program;
} else {
pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false);
@@ -362,7 +362,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
"Cannot find PackageMaker compiler" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath);
}
// Get path to the real PackageMaker, not a symlink:
@@ -427,11 +427,12 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
// Determine the package compatibility version. If it wasn't
// specified by the user, we define it based on which features the
// user requested.
- const char* packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION");
- if (packageCompat && *packageCompat) {
+ cmValue packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION");
+ if (packageCompat && !packageCompat->empty()) {
unsigned int majorVersion = 10;
unsigned int minorVersion = 5;
- int res = sscanf(packageCompat, "%u.%u", &majorVersion, &minorVersion);
+ int res =
+ sscanf(packageCompat->c_str(), "%u.%u", &majorVersion, &minorVersion);
if (res == 2) {
this->PackageCompatibilityVersion =
getVersion(majorVersion, minorVersion);
@@ -454,8 +455,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
"Cannot find hdiutil compiler" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE",
- pkgPath.c_str());
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM_DISK_IMAGE", pkgPath);
return this->Superclass::InitializeInternal();
}
@@ -543,8 +543,7 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
// Create the Info.plist file for this component
std::string moduleVersionSuffix = cmStrCat('.', component.Name);
- this->SetOption("CPACK_MODULE_VERSION_SUFFIX",
- moduleVersionSuffix.c_str());
+ this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix);
std::string infoFileName = cmStrCat(component.Name, "-Info.plist");
if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) {
return false;
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index a3e55de5c..f55b8def0 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
{
@@ -87,11 +88,11 @@ int cmCPackProductBuildGenerator::PackageFiles()
std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD");
std::string identityName;
- if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) {
+ if (cmValue n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) {
identityName = n;
}
std::string keychainPath;
- if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
+ if (cmValue p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
keychainPath = p;
}
@@ -122,7 +123,7 @@ int cmCPackProductBuildGenerator::InitializeInternal()
"Cannot find pkgbuild executable" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_PKGBUILD", program);
program = cmSystemTools::FindProgram("productbuild", no_paths, false);
if (program.empty()) {
@@ -130,7 +131,7 @@ int cmCPackProductBuildGenerator::InitializeInternal()
"Cannot find productbuild executable" << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program.c_str());
+ this->SetOptionIfNotSet("CPACK_COMMAND_PRODUCTBUILD", program);
return this->Superclass::InitializeInternal();
}
@@ -173,8 +174,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
const char* comp_name = component ? component->Name.c_str() : nullptr;
- const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name);
- const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name);
+ cmValue preflight = this->GetComponentScript("PREFLIGHT", comp_name);
+ cmValue postflight = this->GetComponentScript("POSTFLIGHT", comp_name);
std::string resDir = packageFileDir;
if (component) {
@@ -213,11 +214,11 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
std::string version = this->GetOption("CPACK_PACKAGE_VERSION");
std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD");
std::string identityName;
- if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) {
+ if (cmValue n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) {
identityName = n;
}
std::string keychainPath;
- if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
+ if (cmValue p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
keychainPath = p;
}
@@ -239,7 +240,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
return RunProductBuild(pkgCmd.str());
}
-const char* cmCPackProductBuildGenerator::GetComponentScript(
+cmValue cmCPackProductBuildGenerator::GetComponentScript(
const char* script, const char* component_name)
{
std::string scriptname = std::string("CPACK_") + script + "_";
diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h
index 462e2fcc9..31cfafadf 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.h
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -8,6 +8,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackPKGGenerator.h"
+#include "cmValue.h"
class cmCPackComponent;
@@ -45,6 +46,5 @@ protected:
const std::string& packageDir,
const cmCPackComponent* component);
- const char* GetComponentScript(const char* script,
- const char* script_component);
+ cmValue GetComponentScript(const char* script, const char* script_component);
};
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index c3f6d594b..9e50700c6 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmCPackLog.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackRPMGenerator::cmCPackRPMGenerator() = default;
@@ -32,13 +33,13 @@ int cmCPackRPMGenerator::InitializeInternal()
if (this->GetOption("CPACK_PACKAGE_NAME")) {
std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
std::replace(packageName.begin(), packageName.end(), ' ', '-');
- this->SetOption("CPACK_PACKAGE_NAME", packageName.c_str());
+ this->SetOption("CPACK_PACKAGE_NAME", packageName);
}
/* same for CPACK_PACKAGE_FILE_NAME */
if (this->GetOption("CPACK_PACKAGE_FILE_NAME")) {
std::string packageName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
std::replace(packageName.begin(), packageName.end(), ' ', '-');
- this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName.c_str());
+ this->SetOption("CPACK_PACKAGE_FILE_NAME", packageName);
}
return this->Superclass::InitializeInternal();
}
@@ -73,19 +74,17 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
localToplevel += "/" + packageName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel);
packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName);
/* replace the TEMPORARY package file name */
- this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
+ this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName);
// Tell CPackRPM.cmake the name of the component NAME.
- this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str());
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName);
// Tell CPackRPM.cmake the path where the component is.
std::string component_path = cmStrCat('/', packageName);
- this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
- component_path.c_str());
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path);
if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error while execution CPackRPM.cmake" << std::endl);
@@ -103,7 +102,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup)
this->packageFileNames.clear();
std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY"));
- const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
+ cmValue mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT");
if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") &&
!this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) {
@@ -364,19 +363,17 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
localToplevel += "/" + compInstDirName;
/* replace the TEMP DIRECTORY with the component one */
- this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel.c_str());
+ this->SetOption("CPACK_TEMPORARY_DIRECTORY", localToplevel);
packageFileName += "/" + outputFileName;
/* replace proposed CPACK_OUTPUT_FILE_NAME */
- this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName.c_str());
+ this->SetOption("CPACK_OUTPUT_FILE_NAME", outputFileName);
/* replace the TEMPORARY package file name */
- this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
- packageFileName.c_str());
+ this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME", packageFileName);
if (!compInstDirName.empty()) {
// Tell CPackRPM.cmake the path where the component is.
std::string component_path = cmStrCat('/', compInstDirName);
- this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
- component_path.c_str());
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path);
}
if (this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index ad0a3e21b..1340fb59f 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -15,6 +15,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCPackSTGZGenerator::cmCPackSTGZGenerator()
: cmCPackArchiveGenerator(cmArchiveWrite::CompressGZip, "paxr", ".sh")
@@ -33,7 +34,7 @@ int cmCPackSTGZGenerator::InitializeInternal()
"Cannot find template file: " << inFile << std::endl);
return 0;
}
- this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile.c_str());
+ this->SetOptionIfNotSet("CPACK_STGZ_HEADER_FILE", inFile);
this->SetOptionIfNotSet("CPACK_AT_SIGN", "@");
return this->Superclass::InitializeInternal();
@@ -78,8 +79,7 @@ int cmCPackSTGZGenerator::GenerateHeader(std::ostream* os)
while (cmSystemTools::GetLineFromStream(ilfs, line)) {
licenseText += line + "\n";
}
- this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT",
- licenseText.c_str());
+ this->SetOptionIfNotSet("CPACK_RESOURCE_FILE_LICENSE_CONTENT", licenseText);
const char headerLengthTag[] = "###CPACK_HEADER_LENGTH###";
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index a77893903..54fd3587c 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -22,11 +22,11 @@
#include "cmDocumentationFormatter.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -326,11 +326,11 @@ int main(int argc, char const* const* argv)
cmSystemTools::CollapseFullPath(cpackProjectDirectory);
globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);
- cmProp cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
+ cmValue cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH");
if (cpackModulesPath) {
globalMF.AddDefinition("CMAKE_MODULE_PATH", *cpackModulesPath);
}
- cmProp genList = globalMF.GetDefinition("CPACK_GENERATOR");
+ cmValue genList = globalMF.GetDefinition("CPACK_GENERATOR");
if (!genList) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"CPack generator not specified" << std::endl);
@@ -408,20 +408,20 @@ int main(int argc, char const* const* argv)
parsed = 0;
}
if (parsed) {
- cmProp projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
+ cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Use generator: " << cpackGenerator->GetNameOfClass()
<< std::endl);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"For project: " << *projName << std::endl);
- cmProp projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION");
+ cmValue projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION");
if (!projVersion) {
- cmProp projVersionMajor =
+ cmValue projVersionMajor =
mf->GetDefinition("CPACK_PACKAGE_VERSION_MAJOR");
- cmProp projVersionMinor =
+ cmValue projVersionMinor =
mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR");
- cmProp projVersionPatch =
+ cmValue projVersionPatch =
mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
std::ostringstream ostr;
ostr << *projVersionMajor << "." << *projVersionMinor << "."
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index 483c316a6..6e7c9e10f 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -11,9 +11,9 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
class cmExecutionStatus;
@@ -39,13 +39,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
this->Handler = handler;
- cmProp ctestBuildCommand =
+ cmValue ctestBuildCommand =
this->Makefile->GetDefinition("CTEST_BUILD_COMMAND");
if (cmNonempty(ctestBuildCommand)) {
this->CTest->SetCTestConfiguration("MakeCommand", *ctestBuildCommand,
this->Quiet);
} else {
- cmProp cmakeGeneratorName =
+ cmValue cmakeGeneratorName =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
// Build configuration is determined by: CONFIGURATION argument,
@@ -53,7 +53,7 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
// CTEST_CONFIGURATION_TYPE script variable, or ctest -C command
// line argument... in that order.
//
- cmProp ctestBuildConfiguration =
+ cmValue ctestBuildConfiguration =
this->Makefile->GetDefinition("CTEST_BUILD_CONFIGURATION");
std::string cmakeBuildConfiguration = cmNonempty(this->Configuration)
? this->Configuration
@@ -119,13 +119,13 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
}
}
- if (cmProp useLaunchers =
+ if (cmValue useLaunchers =
this->Makefile->GetDefinition("CTEST_USE_LAUNCHERS")) {
this->CTest->SetCTestConfiguration("UseLaunchers", *useLaunchers,
this->Quiet);
}
- if (cmProp labelsForSubprojects =
+ if (cmValue labelsForSubprojects =
this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
*labelsForSubprojects, this->Quiet);
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 03caa6372..f9c4a8e35 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -19,10 +19,10 @@
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
static const char* cmCTestErrorMatches[] = {
@@ -249,11 +249,11 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf)
}
// Record the user-specified custom warning rules.
- if (cmProp customWarningMatchers =
+ if (cmValue customWarningMatchers =
mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) {
cmExpandList(*customWarningMatchers, this->ReallyCustomWarningMatches);
}
- if (cmProp customWarningExceptions =
+ if (cmValue customWarningExceptions =
mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) {
cmExpandList(*customWarningExceptions,
this->ReallyCustomWarningExceptions);
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index db9923e95..fd20398d2 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -12,9 +12,9 @@
#include "cmCTestConfigureHandler.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
void cmCTestConfigureCommand::BindArguments()
@@ -39,14 +39,14 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
return nullptr;
}
- cmProp ctestConfigureCommand =
+ cmValue ctestConfigureCommand =
this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
if (cmNonempty(ctestConfigureCommand)) {
this->CTest->SetCTestConfiguration("ConfigureCommand",
*ctestConfigureCommand, this->Quiet);
} else {
- cmProp cmakeGeneratorName =
+ cmValue cmakeGeneratorName =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
if (cmNonempty(cmakeGeneratorName)) {
const std::string& source_dir =
@@ -106,7 +106,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
cmakeConfigureCommand += *cmakeGeneratorName;
cmakeConfigureCommand += "\"";
- cmProp cmakeGeneratorPlatform =
+ cmValue cmakeGeneratorPlatform =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM");
if (cmNonempty(cmakeGeneratorPlatform)) {
cmakeConfigureCommand += " \"-A";
@@ -114,7 +114,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
cmakeConfigureCommand += "\"";
}
- cmProp cmakeGeneratorToolset =
+ cmValue cmakeGeneratorToolset =
this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET");
if (cmNonempty(cmakeGeneratorToolset)) {
cmakeConfigureCommand += " \"-T";
@@ -137,7 +137,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
}
- if (cmProp labelsForSubprojects =
+ if (cmValue labelsForSubprojects =
this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
*labelsForSubprojects, this->Quiet);
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 568b0917c..d85edcc5f 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -18,6 +18,7 @@
#include "cmProcessTools.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major,
unsigned int minor, unsigned int fix)
diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 48cc0e450..9800192ca 100644
--- a/Source/CTest/cmCTestGenericHandler.cxx
+++ b/Source/CTest/cmCTestGenericHandler.cxx
@@ -21,11 +21,12 @@ cmCTestGenericHandler::cmCTestGenericHandler()
cmCTestGenericHandler::~cmCTestGenericHandler() = default;
+namespace {
/* Modify the given `map`, setting key `op` to `value` if `value`
* is non-null, otherwise removing key `op` (if it exists).
*/
-static void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
- const std::string& op, const char* value)
+void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
+ const std::string& op, const char* value)
{
if (!value) {
map.erase(op);
@@ -34,11 +35,26 @@ static void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
map[op] = value;
}
+void SetMapValue(cmCTestGenericHandler::t_StringToString& map,
+ const std::string& op, cmValue value)
+{
+ if (!value) {
+ map.erase(op);
+ return;
+ }
+
+ map[op] = *value;
+}
+}
void cmCTestGenericHandler::SetOption(const std::string& op, const char* value)
{
SetMapValue(this->Options, op, value);
}
+void cmCTestGenericHandler::SetOption(const std::string& op, cmValue value)
+{
+ SetMapValue(this->Options, op, value);
+}
void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
const char* value)
@@ -46,6 +62,12 @@ void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
this->SetOption(op, value);
SetMapValue(this->PersistentOptions, op, value);
}
+void cmCTestGenericHandler::SetPersistentOption(const std::string& op,
+ cmValue value)
+{
+ this->SetOption(op, value);
+ SetMapValue(this->PersistentOptions, op, value);
+}
void cmCTestGenericHandler::AddMultiOption(const std::string& op,
const std::string& value)
@@ -72,13 +94,13 @@ void cmCTestGenericHandler::Initialize()
this->MultiOptions = this->PersistentMultiOptions;
}
-const char* cmCTestGenericHandler::GetOption(const std::string& op)
+cmValue cmCTestGenericHandler::GetOption(const std::string& op)
{
auto remit = this->Options.find(op);
if (remit == this->Options.end()) {
return nullptr;
}
- return remit->second.c_str();
+ return cmValue(remit->second);
}
std::vector<std::string> cmCTestGenericHandler::GetMultiOption(
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index e846fd956..b4b0ad8a2 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -12,6 +12,7 @@
#include "cmCTest.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmGeneratedFileStream;
class cmMakefile;
@@ -86,8 +87,18 @@ public:
* as a multi-value will return nullptr.
*/
void SetPersistentOption(const std::string& op, const char* value);
+ void SetPersistentOption(const std::string& op, const std::string& value)
+ {
+ this->SetPersistentOption(op, cmValue(value));
+ }
+ void SetPersistentOption(const std::string& op, cmValue value);
void SetOption(const std::string& op, const char* value);
- const char* GetOption(const std::string& op);
+ void SetOption(const std::string& op, const std::string& value)
+ {
+ this->SetOption(op, cmValue(value));
+ }
+ void SetOption(const std::string& op, cmValue value);
+ cmValue GetOption(const std::string& op);
/**
* Multi-Options collect one or more values from flags; passing
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 731932e38..ea8feaa9f 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -14,9 +14,9 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmWorkingDirectory.h"
namespace {
@@ -126,7 +126,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// CTEST_CONFIGURATION_TYPE script variable if it is defined.
// The current script value trumps the -C argument on the command
// line.
- cmProp ctestConfigType =
+ cmValue ctestConfigType =
this->Makefile->GetDefinition("CTEST_CONFIGURATION_TYPE");
if (ctestConfigType) {
this->CTest->SetConfigType(*ctestConfigType);
@@ -161,7 +161,7 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
this->Quiet);
}
- if (cmProp changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) {
+ if (cmValue changeId = this->Makefile->GetDefinition("CTEST_CHANGE_ID")) {
this->CTest->SetCTestConfiguration("ChangeId", *changeId, this->Quiet);
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 125d0034d..6bb8e79c1 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -305,7 +305,7 @@ int cmCTestMemCheckHandler::GetDefectCount() const
return this->DefectCount;
}
-void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
+void cmCTestMemCheckHandler::GenerateCTestXML(cmXMLWriter& xml)
{
if (!this->CTest->GetProduceXML()) {
return;
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index b200c4394..a63a24df1 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -119,9 +119,9 @@ private:
bool InitializeMemoryChecking();
/**
- * Generate the Dart compatible output
+ * Generate CTest DynamicAnalysis.xml files
*/
- void GenerateDartOutput(cmXMLWriter& xml) override;
+ void GenerateCTestXML(cmXMLWriter& xml) override;
std::vector<std::string> CustomPreMemCheck;
std::vector<std::string> CustomPostMemCheck;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 86a8e00a6..d90c4a646 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -1026,6 +1026,11 @@ static Json::Value DumpCTestProperties(
properties.append(DumpCTestProperty(
"ENVIRONMENT", DumpToJsonArray(testProperties.Environment)));
}
+ if (!testProperties.EnvironmentModification.empty()) {
+ properties.append(DumpCTestProperty(
+ "ENVIRONMENT_MODIFICATION",
+ DumpToJsonArray(testProperties.EnvironmentModification)));
+ }
if (!testProperties.ErrorRegularExpressions.empty()) {
properties.append(DumpCTestProperty(
"FAIL_REGULAR_EXPRESSION",
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index a8921134b..9d2cef69f 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -2,17 +2,22 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestRunTest.h"
+#include <algorithm>
#include <chrono>
#include <cstddef> // IWYU pragma: keep
#include <cstdint>
#include <cstdio>
#include <cstring>
+#include <functional>
#include <iomanip>
#include <ratio>
#include <sstream>
#include <utility>
#include <cm/memory>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
@@ -44,7 +49,9 @@ void cmCTestRunTest::CheckOutput(std::string const& line)
// Check for special CTest XML tags in this line of output.
// If any are found, this line is excluded from ProcessOutput.
if (!line.empty() && line.find("<CTest") != std::string::npos) {
+ bool ctest_tag_found = false;
if (this->TestHandler->CustomCompletionStatusRegex.find(line)) {
+ ctest_tag_found = true;
this->TestResult.CustomCompletionStatus =
this->TestHandler->CustomCompletionStatusRegex.match(1);
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -52,6 +59,20 @@ void cmCTestRunTest::CheckOutput(std::string const& line)
<< "Test Details changed to '"
<< this->TestResult.CustomCompletionStatus
<< "'" << std::endl);
+ } else if (this->TestHandler->CustomLabelRegex.find(line)) {
+ ctest_tag_found = true;
+ auto label = this->TestHandler->CustomLabelRegex.match(1);
+ auto& labels = this->TestProperties->Labels;
+ if (std::find(labels.begin(), labels.end(), label) == labels.end()) {
+ labels.push_back(label);
+ std::sort(labels.begin(), labels.end());
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->GetIndex()
+ << ": "
+ << "Test Label added: '" << label << "'" << std::endl);
+ }
+ }
+ if (ctest_tag_found) {
return;
}
}
@@ -245,7 +266,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- this->DartProcessing();
+ this->ParseOutputForMeasurements();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
@@ -623,6 +644,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
&this->TestProperties->Environment,
+ &this->TestProperties->EnvironmentModification,
&this->TestProperties->Affinity);
}
@@ -679,28 +701,45 @@ void cmCTestRunTest::ComputeArguments()
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
this->Index << ": " << env << std::endl);
}
+ if (!this->TestProperties->EnvironmentModification.empty()) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": "
+ << "Environment variable modifications: "
+ << std::endl);
+ }
+ for (std::string const& envmod :
+ this->TestProperties->EnvironmentModification) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ this->Index << ": " << envmod << std::endl);
+ }
}
-void cmCTestRunTest::DartProcessing()
+void cmCTestRunTest::ParseOutputForMeasurements()
{
if (!this->ProcessOutput.empty() &&
- this->ProcessOutput.find("<DartMeasurement") != std::string::npos) {
- if (this->TestHandler->DartStuff.find(this->ProcessOutput)) {
- this->TestResult.DartString = this->TestHandler->DartStuff.match(1);
+ (this->ProcessOutput.find("<DartMeasurement") != std::string::npos ||
+ this->ProcessOutput.find("<CTestMeasurement") != std::string::npos)) {
+ if (this->TestHandler->AllTestMeasurementsRegex.find(
+ this->ProcessOutput)) {
+ this->TestResult.TestMeasurementsOutput =
+ this->TestHandler->AllTestMeasurementsRegex.match(1);
// keep searching and replacing until none are left
- while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) {
+ while (this->TestHandler->SingleTestMeasurementRegex.find(
+ this->ProcessOutput)) {
// replace the exact match for the string
cmSystemTools::ReplaceString(
- this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(),
- "");
+ this->ProcessOutput,
+ this->TestHandler->SingleTestMeasurementRegex.match(1).c_str(), "");
}
}
}
}
-bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment,
- std::vector<size_t>* affinity)
+bool cmCTestRunTest::ForkProcess(
+ cmDuration testTimeOut, bool explicitTimeout,
+ std::vector<std::string>* environment,
+ std::vector<std::string>* environment_modification,
+ std::vector<size_t>* affinity)
{
this->TestProcess->SetId(this->Index);
this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory);
@@ -743,12 +782,145 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
std::ostringstream envMeasurement;
if (environment && !environment->empty()) {
+ // Environment modification works on the assumption that the environment is
+ // actually modified here. If another strategy is used, there will need to
+ // be updates below in `apply_diff`.
cmSystemTools::AppendEnv(*environment);
for (auto const& var : *environment) {
envMeasurement << var << std::endl;
}
}
+ if (environment_modification && !environment_modification->empty()) {
+ std::map<std::string, cm::optional<std::string>> env_application;
+
+#ifdef _WIN32
+ char path_sep = ';';
+#else
+ char path_sep = ':';
+#endif
+
+ auto apply_diff =
+ [&env_application](const std::string& name,
+ std::function<void(std::string&)> const& apply) {
+ cm::optional<std::string> old_value = env_application[name];
+ std::string output;
+ if (old_value) {
+ output = *old_value;
+ } else {
+ // This only works because the environment is actually modified above
+ // (`AppendEnv`). If CTest ever just creates an environment block
+ // directly, that block will need to be queried for the subprocess'
+ // value instead.
+ const char* curval = cmSystemTools::GetEnv(name);
+ if (curval) {
+ output = curval;
+ }
+ }
+ apply(output);
+ env_application[name] = output;
+ };
+
+ bool err_occurred = false;
+
+ for (auto const& envmod : *environment_modification) {
+ // Split on `=`
+ auto const eq_loc = envmod.find_first_of('=');
+ if (eq_loc == std::string::npos) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Missing `=` after the variable name in: "
+ << envmod << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ auto const name = envmod.substr(0, eq_loc);
+
+ // Split value on `:`
+ auto const op_value_start = eq_loc + 1;
+ auto const colon_loc = envmod.find_first_of(':', op_value_start);
+ if (colon_loc == std::string::npos) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Missing `:` after the operation in: " << envmod
+ << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ auto const op =
+ envmod.substr(op_value_start, colon_loc - op_value_start);
+
+ auto const value_start = colon_loc + 1;
+ auto const value = envmod.substr(value_start);
+
+ // Determine what to do with the operation.
+ if (op == "reset"_s) {
+ auto entry = env_application.find(name);
+ if (entry != env_application.end()) {
+ env_application.erase(entry);
+ }
+ } else if (op == "set"_s) {
+ env_application[name] = value;
+ } else if (op == "unset"_s) {
+ env_application[name] = {};
+ } else if (op == "string_append"_s) {
+ apply_diff(name, [&value](std::string& output) { output += value; });
+ } else if (op == "string_prepend"_s) {
+ apply_diff(name,
+ [&value](std::string& output) { output.insert(0, value); });
+ } else if (op == "path_list_append"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output += path_sep;
+ }
+ output += value;
+ });
+ } else if (op == "path_list_prepend"_s) {
+ apply_diff(name, [&value, path_sep](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), path_sep);
+ }
+ output.insert(0, value);
+ });
+ } else if (op == "cmake_list_append"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output += ';';
+ }
+ output += value;
+ });
+ } else if (op == "cmake_list_prepend"_s) {
+ apply_diff(name, [&value](std::string& output) {
+ if (!output.empty()) {
+ output.insert(output.begin(), ';');
+ }
+ output.insert(0, value);
+ });
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Error: Unrecognized environment manipulation argument: "
+ << op << std::endl);
+ err_occurred = true;
+ continue;
+ }
+ }
+
+ if (err_occurred) {
+ return false;
+ }
+
+ for (auto const& env_apply : env_application) {
+ if (env_apply.second) {
+ auto const env_update =
+ cmStrCat(env_apply.first, '=', *env_apply.second);
+ cmSystemTools::PutEnv(env_update);
+ envMeasurement << env_update << std::endl;
+ } else {
+ cmSystemTools::UnsetEnv(env_apply.first.c_str());
+ // Signify that this variable is being actively unset
+ envMeasurement << "#" << env_apply.first << "=" << std::endl;
+ }
+ }
+ }
+
if (this->UseAllocatedResources) {
std::vector<std::string> envLog;
this->SetupResourcesEnvironment(&envLog);
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 863ac1bfd..2082156b8 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -109,10 +109,11 @@ public:
private:
bool NeedsToRepeat();
- void DartProcessing();
+ void ParseOutputForMeasurements();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
std::vector<std::string>* environment,
+ std::vector<std::string>* environment_modification,
std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index d2cad3992..f685f6681 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -34,12 +34,12 @@
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
#ifdef _WIN32
@@ -372,8 +372,8 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
int cmCTestScriptHandler::ExtractVariables()
{
// Temporary variables
- cmProp minInterval;
- cmProp contDuration;
+ cmValue minInterval;
+ cmValue contDuration;
this->SourceDir =
this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
@@ -412,7 +412,7 @@ int cmCTestScriptHandler::ExtractVariables()
int i;
for (i = 1; i < 10; ++i) {
sprintf(updateVar, "CTEST_EXTRA_UPDATES_%i", i);
- cmProp updateVal = this->Makefile->GetDefinition(updateVar);
+ cmValue updateVal = this->Makefile->GetDefinition(updateVar);
if (updateVal) {
if (this->UpdateCmd.empty()) {
cmSystemTools::Error(
@@ -930,7 +930,7 @@ cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed()
return cmCTest::MaxDuration();
}
- cmProp timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT");
+ cmValue timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT");
if (!timelimitS) {
return cmCTest::MaxDuration();
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 53e1b2f96..84d12d77b 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -9,8 +9,8 @@
#include "cmCTestVC.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmExecutionStatus;
@@ -30,8 +30,8 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
size_t cnt = 0;
const char* smodel = nullptr;
- const std::string* src_dir = nullptr;
- const std::string* bld_dir = nullptr;
+ cmValue src_dir;
+ cmValue bld_dir;
while (cnt < args.size()) {
if (args[cnt] == "GROUP" || args[cnt] == "TRACK") {
@@ -55,10 +55,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
smodel = args[cnt].c_str();
cnt++;
} else if (!src_dir) {
- src_dir = &args[cnt];
+ src_dir = cmValue(args[cnt]);
cnt++;
} else if (!bld_dir) {
- bld_dir = &args[cnt];
+ bld_dir = cmValue(args[cnt]);
cnt++;
} else {
this->SetError("Too many arguments");
@@ -162,7 +162,7 @@ bool cmCTestStartCommand::InitialCheckout(std::ostream& ofs,
std::string const& sourceDir)
{
// Use the user-provided command to create the source tree.
- cmProp initialCheckoutCommand =
+ cmValue initialCheckoutCommand =
this->Makefile->GetDefinition("CTEST_CHECKOUT_COMMAND");
if (!initialCheckoutCommand) {
initialCheckoutCommand =
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index bdba0e5d2..c4f87e993 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -16,10 +16,10 @@
#include "cmCommand.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmExecutionStatus;
@@ -36,8 +36,8 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
- const std::string* submitURL = !this->SubmitURL.empty()
- ? &this->SubmitURL
+ cmValue submitURL = !this->SubmitURL.empty()
+ ? cmValue(this->SubmitURL)
: this->Makefile->GetDefinition("CTEST_SUBMIT_URL");
if (submitURL) {
@@ -59,14 +59,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(
this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet);
- cmProp notesFilesVariable =
+ cmValue notesFilesVariable =
this->Makefile->GetDefinition("CTEST_NOTES_FILES");
if (notesFilesVariable) {
std::vector<std::string> notesFiles = cmExpandedList(*notesFilesVariable);
this->CTest->GenerateNotesFile(notesFiles);
}
- cmProp extraFilesVariable =
+ cmValue extraFilesVariable =
this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES");
if (extraFilesVariable) {
std::vector<std::string> extraFiles = cmExpandedList(*extraFilesVariable);
@@ -119,15 +119,15 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
handler->SetHttpHeaders(this->HttpHeaders);
}
- handler->SetOption("RetryDelay", this->RetryDelay.c_str());
- handler->SetOption("RetryCount", this->RetryCount.c_str());
+ handler->SetOption("RetryDelay", this->RetryDelay);
+ handler->SetOption("RetryCount", this->RetryCount);
handler->SetOption("InternalTest", this->InternalTest ? "ON" : "OFF");
handler->SetQuiet(this->Quiet);
if (this->CDashUpload) {
- handler->SetOption("CDashUploadFile", this->CDashUploadFile.c_str());
- handler->SetOption("CDashUploadType", this->CDashUploadType.c_str());
+ handler->SetOption("CDashUploadFile", this->CDashUploadFile);
+ handler->SetOption("CDashUploadType", this->CDashUploadType);
}
return handler;
}
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 5b54573f3..b99bb79d1 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -21,10 +21,10 @@
#include "cmCurl.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLParser.h"
#include "cmake.h"
@@ -261,7 +261,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(
cmCTestScriptHandler* ch = this->CTest->GetScriptHandler();
cmake* cm = ch->GetCMake();
if (cm) {
- cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject");
+ cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject");
if (subproject) {
upload_as += "&subproject=";
upload_as += ctest_curl.Escape(*subproject);
@@ -357,12 +357,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(
// If curl failed for any reason, or checksum fails, wait and retry
//
if (res != CURLE_OK || this->HasErrors) {
- std::string retryDelay = this->GetOption("RetryDelay") == nullptr
- ? ""
- : this->GetOption("RetryDelay");
- std::string retryCount = this->GetOption("RetryCount") == nullptr
- ? ""
- : this->GetOption("RetryCount");
+ std::string retryDelay = *this->GetOption("RetryDelay");
+ std::string retryCount = *this->GetOption("RetryCount");
auto delay = cmDuration(
retryDelay.empty()
@@ -522,12 +518,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
bool internalTest = cmIsOn(this->GetOption("InternalTest"));
// Get RETRY_COUNT and RETRY_DELAY values if they were set.
- std::string retryDelayString = this->GetOption("RetryDelay") == nullptr
- ? ""
- : this->GetOption("RetryDelay");
- std::string retryCountString = this->GetOption("RetryCount") == nullptr
- ? ""
- : this->GetOption("RetryCount");
+ std::string retryDelayString = *this->GetOption("RetryDelay");
+ std::string retryCountString = *this->GetOption("RetryCount");
auto retryDelay = std::chrono::seconds(0);
if (!retryDelayString.empty()) {
unsigned long retryDelayValue = 0;
@@ -556,7 +548,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
// a "&subproject=subprojectname" to the first POST.
cmCTestScriptHandler* ch = this->CTest->GetScriptHandler();
cmake* cm = ch->GetCMake();
- cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject");
+ cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject");
// TODO: Encode values for a URL instead of trusting caller.
std::ostringstream str;
if (subproject) {
@@ -716,8 +708,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
int cmCTestSubmitHandler::ProcessHandler()
{
- const char* cdashUploadFile = this->GetOption("CDashUploadFile");
- const char* cdashUploadType = this->GetOption("CDashUploadType");
+ cmValue cdashUploadFile = this->GetOption("CDashUploadFile");
+ cmValue cdashUploadType = this->GetOption("CDashUploadType");
if (cdashUploadFile && cdashUploadType) {
return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType);
}
@@ -804,6 +796,7 @@ int cmCTestSubmitHandler::ProcessHandler()
}
}
this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml");
+ this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis-Test.xml");
this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml");
this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml");
this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml");
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 67f498608..5488388c8 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -12,8 +12,8 @@
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
void cmCTestTestCommand::BindArguments()
{
@@ -40,7 +40,7 @@ void cmCTestTestCommand::BindArguments()
cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
{
- cmProp ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
+ cmValue ctestTimeout = this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
cmDuration timeout;
if (ctestTimeout) {
@@ -54,7 +54,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
this->CTest->SetTimeOut(timeout);
- cmProp resourceSpecFile =
+ cmValue resourceSpecFile =
this->Makefile->GetDefinition("CTEST_RESOURCE_SPEC_FILE");
if (this->ResourceSpecFile.empty() && resourceSpecFile) {
this->ResourceSpecFile = *resourceSpecFile;
@@ -64,13 +64,13 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
if (!this->Start.empty() || !this->End.empty() || !this->Stride.empty()) {
handler->SetOption(
"TestsToRunInformation",
- cmStrCat(this->Start, ',', this->End, ',', this->Stride).c_str());
+ cmStrCat(this->Start, ',', this->End, ',', this->Stride));
}
if (!this->Exclude.empty()) {
- handler->SetOption("ExcludeRegularExpression", this->Exclude.c_str());
+ handler->SetOption("ExcludeRegularExpression", this->Exclude);
}
if (!this->Include.empty()) {
- handler->SetOption("IncludeRegularExpression", this->Include.c_str());
+ handler->SetOption("IncludeRegularExpression", this->Include);
}
if (!this->ExcludeLabel.empty()) {
handler->AddMultiOption("ExcludeLabelRegularExpression",
@@ -81,30 +81,30 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
if (!this->ExcludeFixture.empty()) {
handler->SetOption("ExcludeFixtureRegularExpression",
- this->ExcludeFixture.c_str());
+ this->ExcludeFixture);
}
if (!this->ExcludeFixtureSetup.empty()) {
handler->SetOption("ExcludeFixtureSetupRegularExpression",
- this->ExcludeFixtureSetup.c_str());
+ this->ExcludeFixtureSetup);
}
if (!this->ExcludeFixtureCleanup.empty()) {
handler->SetOption("ExcludeFixtureCleanupRegularExpression",
- this->ExcludeFixtureCleanup.c_str());
+ this->ExcludeFixtureCleanup);
}
if (this->StopOnFailure) {
handler->SetOption("StopOnFailure", "ON");
}
if (!this->ParallelLevel.empty()) {
- handler->SetOption("ParallelLevel", this->ParallelLevel.c_str());
+ handler->SetOption("ParallelLevel", this->ParallelLevel);
}
if (!this->Repeat.empty()) {
- handler->SetOption("Repeat", this->Repeat.c_str());
+ handler->SetOption("Repeat", this->Repeat);
}
if (!this->ScheduleRandom.empty()) {
- handler->SetOption("ScheduleRandom", this->ScheduleRandom.c_str());
+ handler->SetOption("ScheduleRandom", this->ScheduleRandom);
}
if (!this->ResourceSpecFile.empty()) {
- handler->SetOption("ResourceSpecFile", this->ResourceSpecFile.c_str());
+ handler->SetOption("ResourceSpecFile", this->ResourceSpecFile);
}
if (!this->StopTime.empty()) {
this->CTest->SetStopTime(this->StopTime);
@@ -114,7 +114,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
// or CTEST_TEST_LOAD script variable, or ctest --test-load
// command line argument... in that order.
unsigned long testLoad;
- cmProp ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
+ cmValue ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD");
if (!this->TestLoad.empty()) {
if (!cmStrToULong(this->TestLoad, &testLoad)) {
testLoad = 0;
@@ -134,7 +134,7 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
}
handler->SetTestLoad(testLoad);
- if (cmProp labelsForSubprojects =
+ if (cmValue labelsForSubprojects =
this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
this->CTest->SetCTestConfiguration("LabelsForSubprojects",
*labelsForSubprojects, this->Quiet);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 730ec0f04..6e97a8345 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -32,17 +32,18 @@
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestResourceGroupsLexerHelper.h"
+#include "cmCTestTestMeasurementXMLParser.h"
#include "cmDuration.h"
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
+#include "cmValue.h"
#include "cmWorkingDirectory.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -303,15 +304,24 @@ cmCTestTestHandler::cmCTestTestHandler()
// Support for JUnit XML output.
this->JUnitXMLFileName = "";
- // regex to detect <DartMeasurement>...</DartMeasurement>
- this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)");
- // regex to detect each individual <DartMeasurement>...</DartMeasurement>
- this->DartStuff1.compile(
- "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)");
+ // Regular expressions to scan test output for custom measurements.
- // regex to detect <CTestDetails>...</CTestDetails>
+ // Capture the whole section of test output from the first opening
+ // <(CTest|Dart)Measurement*> tag to the last </(CTest|Dart)Measurement*>
+ // closing tag.
+ this->AllTestMeasurementsRegex.compile(
+ "(<(CTest|Dart)Measurement.*/(CTest|Dart)Measurement[a-zA-Z]*>)");
+
+ // Capture a single <(CTest|Dart)Measurement*> XML element.
+ this->SingleTestMeasurementRegex.compile(
+ "(<(CTest|Dart)Measurement[^<]*</(CTest|Dart)Measurement[a-zA-Z]*>)");
+
+ // Capture content from <CTestDetails>...</CTestDetails>
this->CustomCompletionStatusRegex.compile(
"<CTestDetails>(.*)</CTestDetails>");
+
+ // Capture content from <CTestLabel>...</CTestLabel>
+ this->CustomLabelRegex.compile("<CTestLabel>(.*)</CTestLabel>");
}
void cmCTestTestHandler::Initialize()
@@ -511,7 +521,7 @@ bool cmCTestTestHandler::ProcessOptions()
if (cmIsOn(this->GetOption("ScheduleRandom"))) {
this->CTest->SetScheduleType("Random");
}
- if (const char* repeat = this->GetOption("Repeat")) {
+ if (cmValue repeat = this->GetOption("Repeat")) {
cmsys::RegularExpression repeatRegex(
"^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$");
if (repeatRegex.find(repeat)) {
@@ -536,7 +546,7 @@ bool cmCTestTestHandler::ProcessOptions()
}
}
if (this->GetOption("ParallelLevel")) {
- this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel")));
+ this->CTest->SetParallelLevel(std::stoi(this->GetOption("ParallelLevel")));
}
if (this->GetOption("StopOnFailure")) {
@@ -547,7 +557,7 @@ bool cmCTestTestHandler::ProcessOptions()
this->IncludeLabelRegularExpressions);
BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"),
this->ExcludeLabelRegularExpressions);
- const char* val = this->GetOption("IncludeRegularExpression");
+ cmValue val = this->GetOption("IncludeRegularExpression");
if (val) {
this->UseIncludeRegExp();
this->SetIncludeRegExp(val);
@@ -559,19 +569,19 @@ bool cmCTestTestHandler::ProcessOptions()
}
val = this->GetOption("ExcludeFixtureRegularExpression");
if (val) {
- this->ExcludeFixtureRegExp = val;
+ this->ExcludeFixtureRegExp = *val;
}
val = this->GetOption("ExcludeFixtureSetupRegularExpression");
if (val) {
- this->ExcludeFixtureSetupRegExp = val;
+ this->ExcludeFixtureSetupRegExp = *val;
}
val = this->GetOption("ExcludeFixtureCleanupRegularExpression");
if (val) {
- this->ExcludeFixtureCleanupRegExp = val;
+ this->ExcludeFixtureCleanupRegExp = *val;
}
val = this->GetOption("ResourceSpecFile");
if (val) {
- this->ResourceSpecFile = val;
+ this->ResourceSpecFile = *val;
}
this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed")));
@@ -692,7 +702,22 @@ bool cmCTestTestHandler::GenerateXML()
return false;
}
cmXMLWriter xml(xmlfile);
- this->GenerateDartOutput(xml);
+ this->GenerateCTestXML(xml);
+ }
+
+ if (this->MemCheck) {
+ cmGeneratedFileStream xmlfile;
+ if (!this->StartResultingXML(cmCTest::PartTest, "DynamicAnalysis-Test",
+ xmlfile)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot create testing XML file" << std::endl);
+ this->LogFile = nullptr;
+ return false;
+ }
+ cmXMLWriter xml(xmlfile);
+ // Explicitly call this class' `GenerateCTestXML` method to make `Test.xml`
+ // as well.
+ this->cmCTestTestHandler::GenerateCTestXML(xml);
}
return true;
@@ -1400,7 +1425,7 @@ void cmCTestTestHandler::GenerateTestCommand(
{
}
-void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
+void cmCTestTestHandler::GenerateCTestXML(cmXMLWriter& xml)
{
if (!this->CTest->GetProduceXML()) {
return;
@@ -1436,7 +1461,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Element("Value", result.ReturnValue);
xml.EndElement(); // NamedMeasurement
}
- this->GenerateRegressionImages(xml, result.DartString);
+ this->RecordCustomTestMeasurements(xml, result.TestMeasurementsOutput);
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "numeric/double");
xml.Attribute("name", "Execution Time");
@@ -1804,7 +1829,7 @@ bool cmCTestTestHandler::GetListOfTests()
// SEND_ERROR or FATAL_ERROR in CTestTestfile or TEST_INCLUDE_FILES
return false;
}
- cmProp specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE");
+ cmValue specFile = mf.GetDefinition("CTEST_RESOURCE_SPEC_FILE");
if (this->ResourceSpecFile.empty() && specFile) {
this->ResourceSpecFile = *specFile;
}
@@ -1976,124 +2001,48 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
}
}
-// Just for convenience
-#define SPACE_REGEX "[ \t\r\n]"
-void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
- const std::string& dart)
-{
- cmsys::RegularExpression twoattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression threeattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression fourattributes(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurement>");
- cmsys::RegularExpression cdatastart(
- "<DartMeasurement" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>" SPACE_REGEX "*<!\\[CDATA\\[");
- cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>");
- cmsys::RegularExpression measurementfile(
- "<DartMeasurementFile" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX
- "*>([^<]*)</DartMeasurementFile>");
-
- bool done = false;
- std::string cxml = dart;
- while (!done) {
- if (twoattributes.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2));
- xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4));
- xml.Element("Value", twoattributes.match(5));
- xml.EndElement();
- cxml.erase(twoattributes.start(),
- twoattributes.end() - twoattributes.start());
- } else if (threeattributes.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(threeattributes.match(1).c_str(),
- threeattributes.match(2));
- xml.Attribute(threeattributes.match(3).c_str(),
- threeattributes.match(4));
- xml.Attribute(threeattributes.match(5).c_str(),
- threeattributes.match(6));
- xml.Element("Value", twoattributes.match(7));
- xml.EndElement();
- cxml.erase(threeattributes.start(),
- threeattributes.end() - threeattributes.start());
- } else if (fourattributes.find(cxml)) {
+void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml,
+ std::string content)
+{
+ while (this->SingleTestMeasurementRegex.find(content)) {
+ // Extract regex match from content and parse it as an XML element.
+ auto measurement_str = this->SingleTestMeasurementRegex.match(1);
+ auto parser = cmCTestTestMeasurementXMLParser();
+ parser.Parse(measurement_str.c_str());
+
+ if (parser.ElementName == "CTestMeasurement" ||
+ parser.ElementName == "DartMeasurement") {
xml.StartElement("NamedMeasurement");
- xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2));
- xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4));
- xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6));
- xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8));
- xml.Element("Value", twoattributes.match(9));
+ xml.Attribute("type", parser.MeasurementType);
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Element("Value", parser.CharacterData);
xml.EndElement();
- cxml.erase(fourattributes.start(),
- fourattributes.end() - fourattributes.start());
- } else if (cdatastart.find(cxml) && cdataend.find(cxml)) {
- xml.StartElement("NamedMeasurement");
- xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2));
- xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4));
- xml.StartElement("Value");
- xml.CData(
- cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()));
- xml.EndElement(); // Value
- xml.EndElement(); // NamedMeasurement
- cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start());
- } else if (measurementfile.find(cxml)) {
- const std::string& filename =
- cmCTest::CleanString(measurementfile.match(5));
- if (cmSystemTools::FileExists(filename)) {
+ } else if (parser.ElementName == "CTestMeasurementFile" ||
+ parser.ElementName == "DartMeasurementFile") {
+ const std::string& filename = cmCTest::CleanString(parser.CharacterData);
+ if (!cmSystemTools::FileExists(filename)) {
+ xml.StartElement("NamedMeasurement");
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("text", "text/string");
+ xml.Element("Value", "File " + filename + " not found");
+ xml.EndElement();
+ cmCTestOptionalLog(
+ this->CTest, HANDLER_OUTPUT,
+ "File \"" << filename << "\" not found." << std::endl, this->Quiet);
+ } else {
long len = cmSystemTools::FileLength(filename);
- std::string k1 = measurementfile.match(1);
- std::string v1 = measurementfile.match(2);
- std::string k2 = measurementfile.match(3);
- std::string v2 = measurementfile.match(4);
if (len == 0) {
- if (cmSystemTools::LowerCase(k1) == "type") {
- v1 = "text/string";
- }
- if (cmSystemTools::LowerCase(k2) == "type") {
- v2 = "text/string";
- }
-
xml.StartElement("NamedMeasurement");
- xml.Attribute(k1.c_str(), v1);
- xml.Attribute(k2.c_str(), v2);
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("type", "text/string");
xml.Attribute("encoding", "none");
xml.Element("Value", "Image " + filename + " is empty");
xml.EndElement();
} else {
- std::string type;
- std::string name;
- if (cmSystemTools::LowerCase(k1) == "type") {
- type = v1;
- } else if (cmSystemTools::LowerCase(k2) == "type") {
- type = v2;
- }
- if (cmSystemTools::LowerCase(k1) == "name") {
- name = v1;
- } else if (cmSystemTools::LowerCase(k2) == "name") {
- name = v2;
- }
- if (type == "file") {
+ if (parser.MeasurementType == "file") {
// Treat this measurement like an "ATTACHED_FILE" when the type
// is explicitly "file" (not an image).
- this->AttachFile(xml, filename, name);
+ this->AttachFile(xml, filename, parser.MeasurementName);
} else {
cmsys::ifstream ifs(filename.c_str(),
std::ios::in
@@ -2110,10 +2059,8 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
encoded_buffer.get(), 1);
xml.StartElement("NamedMeasurement");
- xml.Attribute(measurementfile.match(1).c_str(),
- measurementfile.match(2));
- xml.Attribute(measurementfile.match(3).c_str(),
- measurementfile.match(4));
+ xml.Attribute("name", parser.MeasurementName);
+ xml.Attribute("type", parser.MeasurementType);
xml.Attribute("encoding", "base64");
std::ostringstream ostr;
for (size_t cc = 0; cc < rlen; cc++) {
@@ -2126,48 +2073,34 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
xml.EndElement(); // NamedMeasurement
}
}
- } else {
- int idx = 4;
- if (measurementfile.match(1) == "name") {
- idx = 2;
- }
- xml.StartElement("NamedMeasurement");
- xml.Attribute("name", measurementfile.match(idx));
- xml.Attribute("text", "text/string");
- xml.Element("Value", "File " + filename + " not found");
- xml.EndElement();
- cmCTestOptionalLog(
- this->CTest, HANDLER_OUTPUT,
- "File \"" << filename << "\" not found." << std::endl, this->Quiet);
}
- cxml.erase(measurementfile.start(),
- measurementfile.end() - measurementfile.start());
- } else {
- done = true;
}
+
+ // Remove this element from content.
+ cmSystemTools::ReplaceString(content, measurement_str.c_str(), "");
}
}
-void cmCTestTestHandler::SetIncludeRegExp(const char* arg)
+void cmCTestTestHandler::SetIncludeRegExp(const std::string& arg)
{
this->IncludeRegExp = arg;
}
-void cmCTestTestHandler::SetExcludeRegExp(const char* arg)
+void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg)
{
this->ExcludeRegExp = arg;
}
-void cmCTestTestHandler::SetTestsToRunInformation(const char* in)
+void cmCTestTestHandler::SetTestsToRunInformation(cmValue in)
{
if (!in) {
return;
}
- this->TestsToRunString = in;
+ this->TestsToRunString = *in;
// if the argument is a file, then read it and use the contents as the
// string
if (cmSystemTools::FileExists(in)) {
- cmsys::ifstream fin(in);
+ cmsys::ifstream fin(in->c_str());
unsigned long filelen = cmSystemTools::FileLength(in);
auto buff = cm::make_unique<char[]>(filelen + 1);
fin.getline(buff.get(), filelen);
@@ -2247,7 +2180,7 @@ bool cmCTestTestHandler::SetTestsProperties(
// Ensure we have complete triples otherwise the data is corrupt.
if (triples.size() % 3 == 0) {
- cmState state;
+ cmState state(cmState::Unknown);
rt.Backtrace = cmListFileBacktrace(state.CreateBaseSnapshot());
// the first entry represents the top of the trace so we need to
@@ -2327,6 +2260,8 @@ bool cmCTestTestHandler::SetTestsProperties(
cmExpandList(val, rt.Depends);
} else if (key == "ENVIRONMENT"_s) {
cmExpandList(val, rt.Environment);
+ } else if (key == "ENVIRONMENT_MODIFICATION"_s) {
+ cmExpandList(val, rt.EnvironmentModification);
} else if (key == "LABELS"_s) {
std::vector<std::string> Labels = cmExpandedList(val);
rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end());
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index bd51738b8..3ac05e7bf 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -22,6 +22,7 @@
#include "cmCTestResourceSpec.h"
#include "cmDuration.h"
#include "cmListFileCache.h"
+#include "cmValue.h"
class cmMakefile;
class cmXMLWriter;
@@ -65,8 +66,8 @@ public:
/// them on
void UseIncludeRegExp();
void UseExcludeRegExp();
- void SetIncludeRegExp(const char*);
- void SetExcludeRegExp(const char*);
+ void SetIncludeRegExp(const std::string&);
+ void SetExcludeRegExp(const std::string&);
void SetMaxIndex(int n) { this->MaxIndex = n; }
int GetMaxIndex() { return this->MaxIndex; }
@@ -81,7 +82,7 @@ public:
}
//! pass the -I argument down
- void SetTestsToRunInformation(const char*);
+ void SetTestsToRunInformation(cmValue);
cmCTestTestHandler();
@@ -151,6 +152,7 @@ public:
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
+ std::vector<std::string> EnvironmentModification;
std::vector<std::string> Labels;
std::set<std::string> LockedResources;
std::set<std::string> FixturesSetup;
@@ -177,7 +179,7 @@ public:
std::string CompletionStatus;
std::string CustomCompletionStatus;
std::string Output;
- std::string DartString;
+ std::string TestMeasurementsOutput;
int TestCount;
cmCTestTestProperties* Properties;
};
@@ -276,9 +278,9 @@ public:
private:
/**
- * Generate the Dart compatible output
+ * Write test results in CTest's Test.xml format
*/
- virtual void GenerateDartOutput(cmXMLWriter& xml);
+ virtual void GenerateCTestXML(cmXMLWriter& xml);
/**
* Write test results in JUnit XML format
@@ -348,8 +350,7 @@ private:
cmCTestResourceSpec ResourceSpec;
std::string ResourceSpecFile;
- void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart);
- cmsys::RegularExpression DartStuff1;
+ void RecordCustomTestMeasurements(cmXMLWriter& xml, std::string content);
void CheckLabelFilter(cmCTestTestProperties& it);
void CheckLabelFilterExclude(cmCTestTestProperties& it);
void CheckLabelFilterInclude(cmCTestTestProperties& it);
@@ -358,8 +359,10 @@ private:
bool UseUnion;
ListOfTests TestList;
size_t TotalNumberOfTests;
- cmsys::RegularExpression DartStuff;
+ cmsys::RegularExpression AllTestMeasurementsRegex;
+ cmsys::RegularExpression SingleTestMeasurementRegex;
cmsys::RegularExpression CustomCompletionStatusRegex;
+ cmsys::RegularExpression CustomLabelRegex;
std::ostream* LogFile;
diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.cxx b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx
new file mode 100644
index 000000000..636be2451
--- /dev/null
+++ b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx
@@ -0,0 +1,26 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmCTestTestMeasurementXMLParser.h"
+
+#include <cstring>
+
+void cmCTestTestMeasurementXMLParser::StartElement(const std::string& name,
+ const char** attributes)
+{
+ this->CharacterData.clear();
+ this->ElementName = name;
+ for (const char** attr = attributes; *attr; attr += 2) {
+ if (strcmp(attr[0], "name") == 0) {
+ this->MeasurementName = attr[1];
+ } else if (strcmp(attr[0], "type") == 0) {
+ this->MeasurementType = attr[1];
+ }
+ }
+}
+
+void cmCTestTestMeasurementXMLParser::CharacterDataHandler(const char* data,
+ int length)
+{
+ this->CharacterData.append(data, length);
+}
diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.h b/Source/CTest/cmCTestTestMeasurementXMLParser.h
new file mode 100644
index 000000000..b2c3eb3f1
--- /dev/null
+++ b/Source/CTest/cmCTestTestMeasurementXMLParser.h
@@ -0,0 +1,21 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include <string>
+
+#include "cmXMLParser.h"
+
+class cmCTestTestMeasurementXMLParser : public cmXMLParser
+{
+public:
+ cmCTestTestMeasurementXMLParser() {}
+ std::string CharacterData;
+ std::string ElementName;
+ std::string MeasurementName;
+ std::string MeasurementType;
+
+protected:
+ void StartElement(const std::string& name, const char** atts) override;
+ void EndElement(const std::string& /*name*/) override {}
+ void CharacterDataHandler(const char* data, int length) override;
+};
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 797cb014e..6655bf724 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -79,7 +79,7 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->SetError("source directory not specified. Please use SOURCE tag");
return nullptr;
}
- handler->SetOption("SourceDirectory", source_dir.c_str());
+ handler->SetOption("SourceDirectory", source_dir);
handler->SetQuiet(this->Quiet);
return handler;
}
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 57cc02420..d448c769e 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -19,6 +19,7 @@
#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmXMLWriter.h"
@@ -108,7 +109,7 @@ int cmCTestUpdateHandler::ProcessHandler()
static_cast<void>(fixLocale);
// Get source dir
- const char* sourceDirectory = this->GetOption("SourceDirectory");
+ cmValue sourceDirectory = this->GetOption("SourceDirectory");
if (!sourceDirectory) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot find SourceDirectory key in the DartConfiguration.tcl"
@@ -257,7 +258,7 @@ int cmCTestUpdateHandler::ProcessHandler()
return updated && loadedMods ? numUpdated : -1;
}
-int cmCTestUpdateHandler::DetectVCS(const char* dir)
+int cmCTestUpdateHandler::DetectVCS(const std::string& dir)
{
std::string sourceDirectory = dir;
cmCTestOptionalLog(this->CTest, DEBUG,
diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h
index 25bbb2f5c..70269ea54 100644
--- a/Source/CTest/cmCTestUpdateHandler.h
+++ b/Source/CTest/cmCTestUpdateHandler.h
@@ -59,6 +59,6 @@ private:
std::string UpdateCommand;
int UpdateType;
- int DetectVCS(const char* dir);
+ int DetectVCS(const std::string& dir);
bool SelectVCS();
};
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index 452d7143b..423b5064c 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -10,8 +10,8 @@
#include "cmsys/Process.h"
#include "cmCTest.h"
-#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
cmCTestVC::cmCTestVC(cmCTest* ct, std::ostream& log)
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index 35f09fd6a..e9ec09ee2 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -15,11 +15,11 @@
#include "cmCursesPathWidget.h"
#include "cmCursesStringWidget.h"
#include "cmCursesWidget.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
const std::string& key, int labelwidth, int entrywidth)
@@ -49,7 +49,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
}
- cmProp value = state->GetCacheEntryValue(key);
+ cmValue value = state->GetCacheEntryValue(key);
assert(value);
switch (state->GetCacheEntryType(key)) {
case cmStateEnums::BOOL: {
@@ -72,7 +72,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
break;
}
case cmStateEnums::STRING: {
- cmProp stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
+ cmValue stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
if (stringsProp) {
auto ow =
cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1);
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 069c02ef8..b28c5b7ac 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -17,11 +17,11 @@
#include "cmCursesStandardIncludes.h"
#include "cmCursesStringWidget.h"
#include "cmCursesWidget.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -162,7 +162,7 @@ void cmCursesMainForm::RePost()
// If normal mode, count only non-advanced entries
this->NumberOfVisibleEntries = 0;
for (cmCursesCacheEntryComposite& entry : this->Entries) {
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
@@ -183,7 +183,7 @@ void cmCursesMainForm::RePost()
// Assign fields
for (cmCursesCacheEntryComposite& entry : this->Entries) {
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
@@ -242,7 +242,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
// If normal, display only non-advanced entries
this->NumberOfVisibleEntries = 0;
for (cmCursesCacheEntryComposite& entry : this->Entries) {
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
@@ -260,7 +260,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
bool isNewPage;
int i = 0;
for (cmCursesCacheEntryComposite& entry : this->Entries) {
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
bool advanced =
this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
@@ -406,9 +406,9 @@ void cmCursesMainForm::UpdateStatusBar(cm::optional<std::string> message)
// Get the help string of the current entry
// and add it to the help string
auto* cmakeState = this->CMakeInstance->GetState();
- cmProp existingValue = cmakeState->GetCacheEntryValue(labelValue);
+ cmValue existingValue = cmakeState->GetCacheEntryValue(labelValue);
if (existingValue) {
- cmProp help =
+ cmValue help =
cmakeState->GetCacheEntryProperty(labelValue, "HELPSTRING");
if (help) {
bar += *help;
@@ -618,7 +618,7 @@ void cmCursesMainForm::FillCacheManagerFromUI()
{
for (cmCursesCacheEntryComposite& entry : this->Entries) {
const std::string& cacheKey = entry.Key;
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
if (existingValue) {
std::string oldValue = *existingValue;
@@ -804,9 +804,9 @@ void cmCursesMainForm::HandleInput()
cmCursesWidget* lbl = reinterpret_cast<cmCursesWidget*>(
field_userptr(this->Fields[findex - 2]));
const char* curField = lbl->GetValue();
- cmProp helpString = nullptr;
+ cmValue helpString = nullptr;
- cmProp existingValue =
+ cmValue existingValue =
this->CMakeInstance->GetState()->GetCacheEntryValue(curField);
if (existingValue) {
helpString = this->CMakeInstance->GetState()->GetCacheEntryProperty(
diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 3f3dddeb4..50e97529b 100644
--- a/Source/LexerParser/cmFortranParser.cxx
+++ b/Source/LexerParser/cmFortranParser.cxx
@@ -600,12 +600,12 @@ static const yytype_int8 yytranslate[] =
static const yytype_uint8 yyrline[] =
{
0, 101, 101, 101, 104, 108, 113, 122, 128, 135,
- 140, 144, 149, 157, 162, 167, 172, 177, 182, 187,
- 192, 197, 201, 205, 209, 213, 214, 219, 219, 219,
- 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
- 225, 225, 226, 226, 227, 227, 228, 228, 231, 232,
- 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
- 243, 244, 245, 246, 247
+ 140, 144, 149, 161, 166, 171, 176, 181, 186, 191,
+ 196, 201, 205, 209, 213, 217, 218, 223, 223, 223,
+ 224, 224, 225, 225, 226, 226, 227, 227, 228, 228,
+ 229, 229, 230, 230, 231, 231, 232, 232, 235, 236,
+ 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251
};
#endif
@@ -1747,142 +1747,146 @@ yyreduce:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, (yyvsp[-2].string));
}
+ if (cmsysString_strcasecmp((yyvsp[-4].string), "intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUseIntrinsic(parser, (yyvsp[-2].string));
+ }
free((yyvsp[-4].string));
free((yyvsp[-2].string));
}
-#line 1754 "cmFortranParser.cxx"
+#line 1758 "cmFortranParser.cxx"
break;
case 13: /* stmt: INCLUDE STRING other EOSTMT */
-#line 157 "cmFortranParser.y"
+#line 161 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1764 "cmFortranParser.cxx"
+#line 1768 "cmFortranParser.cxx"
break;
case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */
-#line 162 "cmFortranParser.y"
+#line 166 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1774 "cmFortranParser.cxx"
+#line 1778 "cmFortranParser.cxx"
break;
case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */
-#line 167 "cmFortranParser.y"
+#line 171 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1784 "cmFortranParser.cxx"
+#line 1788 "cmFortranParser.cxx"
break;
case 16: /* stmt: include STRING other EOSTMT */
-#line 172 "cmFortranParser.y"
+#line 176 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleInclude(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1794 "cmFortranParser.cxx"
+#line 1798 "cmFortranParser.cxx"
break;
case 17: /* stmt: define WORD other EOSTMT */
-#line 177 "cmFortranParser.y"
+#line 181 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleDefine(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1804 "cmFortranParser.cxx"
+#line 1808 "cmFortranParser.cxx"
break;
case 18: /* stmt: undef WORD other EOSTMT */
-#line 182 "cmFortranParser.y"
+#line 186 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1814 "cmFortranParser.cxx"
+#line 1818 "cmFortranParser.cxx"
break;
case 19: /* stmt: ifdef WORD other EOSTMT */
-#line 187 "cmFortranParser.y"
+#line 191 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1824 "cmFortranParser.cxx"
+#line 1828 "cmFortranParser.cxx"
break;
case 20: /* stmt: ifndef WORD other EOSTMT */
-#line 192 "cmFortranParser.y"
+#line 196 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string));
free((yyvsp[-2].string));
}
-#line 1834 "cmFortranParser.cxx"
+#line 1838 "cmFortranParser.cxx"
break;
case 21: /* stmt: if other EOSTMT */
-#line 197 "cmFortranParser.y"
+#line 201 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleIf(parser);
}
-#line 1843 "cmFortranParser.cxx"
+#line 1847 "cmFortranParser.cxx"
break;
case 22: /* stmt: elif other EOSTMT */
-#line 201 "cmFortranParser.y"
+#line 205 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElif(parser);
}
-#line 1852 "cmFortranParser.cxx"
+#line 1856 "cmFortranParser.cxx"
break;
case 23: /* stmt: else other EOSTMT */
-#line 205 "cmFortranParser.y"
+#line 209 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleElse(parser);
}
-#line 1861 "cmFortranParser.cxx"
+#line 1865 "cmFortranParser.cxx"
break;
case 24: /* stmt: endif other EOSTMT */
-#line 209 "cmFortranParser.y"
+#line 213 "cmFortranParser.y"
{
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleEndif(parser);
}
-#line 1870 "cmFortranParser.cxx"
+#line 1874 "cmFortranParser.cxx"
break;
case 48: /* misc_code: WORD */
-#line 231 "cmFortranParser.y"
+#line 235 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1876 "cmFortranParser.cxx"
+#line 1880 "cmFortranParser.cxx"
break;
case 55: /* misc_code: STRING */
-#line 238 "cmFortranParser.y"
+#line 242 "cmFortranParser.y"
{ free ((yyvsp[0].string)); }
-#line 1882 "cmFortranParser.cxx"
+#line 1886 "cmFortranParser.cxx"
break;
-#line 1886 "cmFortranParser.cxx"
+#line 1890 "cmFortranParser.cxx"
default: break;
}
@@ -2107,6 +2111,6 @@ yyreturn:
return yyresult;
}
-#line 250 "cmFortranParser.y"
+#line 254 "cmFortranParser.y"
/* End of grammar */
diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y
index a3e1c24b1..8ef19035c 100644
--- a/Source/LexerParser/cmFortranParser.y
+++ b/Source/LexerParser/cmFortranParser.y
@@ -151,6 +151,10 @@ stmt:
cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
cmFortranParser_RuleUse(parser, $5);
}
+ if (cmsysString_strcasecmp($3, "intrinsic") == 0) {
+ cmFortranParser* parser = cmFortran_yyget_extra(yyscanner);
+ cmFortranParser_RuleUseIntrinsic(parser, $5);
+ }
free($3);
free($5);
}
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index c55604980..8ffa3e728 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -10,15 +10,6 @@
#include <QTranslator>
#include <QtPlugin>
-// FIXME(#23565): Qt6 has QTextCodec in Core5Compat, but using its
-// `setCodecForLocale` does not make cmake-gui support non-ASCII chars
-// on Windows. For now we only support them with Qt5. How do we support
-// them with Qt6, preferably without Core5Compat?
-#if defined(Q_OS_WIN) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
-# include <QTextCodec>
-# define CMAKE_HAVE_QTEXTCODEC
-#endif
-
#include "cmsys/CommandLineArguments.hxx"
#include "cmsys/Encoding.hxx"
#include "cmsys/SystemTools.hxx"
@@ -133,11 +124,6 @@ int main(int argc, char** argv)
setlocale(LC_NUMERIC, "C");
-#ifdef CMAKE_HAVE_QTEXTCODEC
- QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
- QTextCodec::setCodecForLocale(utf8_codec);
-#endif
-
// tell the cmake library where cmake is
QDir cmExecDir(QApplication::applicationDirPath());
#if defined(Q_OS_MAC)
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index e6faef470..8ab86564c 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -122,26 +122,26 @@ void QCMake::setBinaryDirectory(const QString& _dir)
QCMakePropertyList props = this->properties();
emit this->propertiesChanged(props);
- cmProp homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
+ cmValue homeDir = state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
if (homeDir) {
setSourceDirectory(QString::fromLocal8Bit(homeDir->c_str()));
}
- cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
+ cmValue gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
if (gen) {
- const std::string* extraGen =
+ cmValue extraGen =
state->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string curGen =
- cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
- *gen, extraGen ? *extraGen : "");
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(*gen,
+ *extraGen);
this->setGenerator(QString::fromLocal8Bit(curGen.c_str()));
}
- cmProp platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
+ cmValue platform = state->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
if (platform) {
this->setPlatform(QString::fromLocal8Bit(platform->c_str()));
}
- cmProp toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
+ cmValue toolset = state->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
if (toolset) {
this->setToolset(QString::fromLocal8Bit(toolset->c_str()));
}
@@ -396,11 +396,11 @@ QCMakePropertyList QCMake::properties() const
continue;
}
- cmProp cachedValue = state->GetCacheEntryValue(key);
+ cmValue cachedValue = state->GetCacheEntryValue(key);
QCMakeProperty prop;
prop.Key = QString::fromLocal8Bit(key.c_str());
- if (cmProp hs = state->GetCacheEntryProperty(key, "HELPSTRING")) {
+ if (cmValue hs = state->GetCacheEntryProperty(key, "HELPSTRING")) {
prop.Help = QString::fromLocal8Bit(hs->c_str());
}
prop.Value = QString::fromLocal8Bit(cachedValue->c_str());
@@ -414,7 +414,7 @@ QCMakePropertyList QCMake::properties() const
prop.Type = QCMakeProperty::FILEPATH;
} else if (t == cmStateEnums::STRING) {
prop.Type = QCMakeProperty::STRING;
- cmProp stringsProperty = state->GetCacheEntryProperty(key, "STRINGS");
+ cmValue stringsProperty = state->GetCacheEntryProperty(key, "STRINGS");
if (stringsProperty) {
prop.Strings =
QString::fromLocal8Bit(stringsProperty->c_str()).split(";");
@@ -550,17 +550,14 @@ void QCMake::loadPresets()
}
QCMakePreset preset;
- preset.name = std::move(QString::fromLocal8Bit(p.Name.data()));
- preset.displayName =
- std::move(QString::fromLocal8Bit(p.DisplayName.data()));
- preset.description =
- std::move(QString::fromLocal8Bit(p.Description.data()));
- preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data()));
- preset.architecture =
- std::move(QString::fromLocal8Bit(p.Architecture.data()));
+ preset.name = QString::fromLocal8Bit(p.Name.data());
+ preset.displayName = QString::fromLocal8Bit(p.DisplayName.data());
+ preset.description = QString::fromLocal8Bit(p.Description.data());
+ preset.generator = QString::fromLocal8Bit(p.Generator.data());
+ preset.architecture = QString::fromLocal8Bit(p.Architecture.data());
preset.setArchitecture = !p.ArchitectureStrategy ||
p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
- preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
+ preset.toolset = QString::fromLocal8Bit(p.Toolset.data());
preset.setToolset = !p.ToolsetStrategy ||
p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set;
preset.enabled = it.Expanded && it.Expanded->ConditionResult &&
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 92e04e43c..a5d1f6a07 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -12,6 +12,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
+#include "cmValue.h"
bool cmAddLibraryCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index 205c1c7a5..a0d5732fd 100644
--- a/Source/cmAddTestCommand.cxx
+++ b/Source/cmAddTestCommand.cxx
@@ -140,7 +140,7 @@ bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args,
test->SetOldStyle(false);
test->SetCommand(command);
if (!working_directory.empty()) {
- test->SetProperty("WORKING_DIRECTORY", working_directory.c_str());
+ test->SetProperty("WORKING_DIRECTORY", working_directory);
}
test->SetCommandExpandLists(command_expand_lists);
mf.AddTestGenerator(cm::make_unique<cmTestGenerator>(test, configurations));
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index c192e2a7b..a1830f9f8 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -60,6 +60,10 @@ class cmListFileBacktrace;
using cmBacktraceRange =
cmRange<std::vector<cmListFileBacktrace>::const_iterator>;
+template <typename T>
+class BT;
+using cmBTStringRange = cmRange<std::vector<BT<std::string>>::const_iterator>;
+
template <typename Range>
typename Range::const_iterator cmRemoveN(Range& r, size_t n)
{
@@ -133,7 +137,13 @@ ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
}
template <typename Range>
-typename Range::const_iterator cmRemoveDuplicates(Range& r)
+typename Range::iterator cmRemoveDuplicates(Range& r)
+{
+ return cmRemoveDuplicates(r.begin(), r.end());
+}
+
+template <typename Range>
+typename Range::const_iterator cmRemoveDuplicates(Range const& r)
{
return cmRemoveDuplicates(r.begin(), r.end());
}
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 54b299824..9e0d80c09 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -250,6 +250,9 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
bool cmArchiveWrite::Open()
{
+ if (!this->Error.empty()) {
+ return false;
+ }
if (archive_write_open(
this->Archive, this, nullptr,
reinterpret_cast<archive_write_callback*>(&Callback::Write),
diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx
index 99707a3f7..a69c00d30 100644
--- a/Source/cmBinUtilsLinuxELFLinker.cxx
+++ b/Source/cmBinUtilsLinuxELFLinker.cxx
@@ -11,6 +11,7 @@
#include <cmsys/RegularExpression.hxx>
#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h"
+#include "cmELF.h"
#include "cmLDConfigLDConfigTool.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -18,10 +19,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
-#ifdef CMake_USE_ELF_PARSER
-# include "cmELF.h"
-#endif
-
static std::string ReplaceOrigin(const std::string& rpath,
const std::string& origin)
{
@@ -91,7 +88,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
{
std::vector<std::string> parentRpaths;
-#ifdef CMake_USE_ELF_PARSER
cmELF elf(file.c_str());
if (!elf) {
return false;
@@ -106,7 +102,6 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
this->Machine = elf.GetMachine();
}
}
-#endif
return this->ScanDependencies(file, parentRpaths);
}
@@ -175,15 +170,11 @@ bool cmBinUtilsLinuxELFLinker::ScanDependencies(
namespace {
bool FileHasArchitecture(const char* filename, std::uint16_t machine)
{
-#ifdef CMake_USE_ELF_PARSER
cmELF elf(filename);
if (!elf) {
return false;
}
return machine == 0 || machine == elf.GetMachine();
-#else
- return true;
-#endif
}
}
diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx
index 47f77d8b9..c0643776c 100644
--- a/Source/cmBinUtilsMacOSMachOLinker.cxx
+++ b/Source/cmBinUtilsMacOSMachOLinker.cxx
@@ -5,6 +5,8 @@
#include <sstream>
#include <string>
+#include <type_traits>
+#include <utility>
#include <vector>
#include <cm/memory>
@@ -52,6 +54,26 @@ bool cmBinUtilsMacOSMachOLinker::Prepare()
return true;
}
+auto cmBinUtilsMacOSMachOLinker::GetFileInfo(std::string const& file)
+ -> const FileInfo*
+{
+ // Memoize processed rpaths and library dependencies to reduce the number
+ // of calls to otool, especially in the case of heavily recursive libraries
+ auto iter = ScannedFileInfo.find(file);
+ if (iter != ScannedFileInfo.end()) {
+ return &iter->second;
+ }
+
+ FileInfo file_info;
+ if (!this->Tool->GetFileInfo(file, file_info.libs, file_info.rpaths)) {
+ // Call to otool failed
+ return nullptr;
+ }
+
+ auto iter_inserted = ScannedFileInfo.insert({ file, std::move(file_info) });
+ return &iter_inserted.first->second;
+}
+
bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
std::string const& file, cmStateEnums::TargetType type)
{
@@ -65,12 +87,12 @@ bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
if (!executableFile.empty()) {
executablePath = cmSystemTools::GetFilenamePath(executableFile);
}
- std::vector<std::string> libs;
- std::vector<std::string> rpaths;
- if (!this->Tool->GetFileInfo(file, libs, rpaths)) {
+ const FileInfo* file_info = this->GetFileInfo(file);
+ if (file_info == nullptr) {
return false;
}
- return this->ScanDependencies(file, libs, rpaths, executablePath);
+ return this->ScanDependencies(file, file_info->libs, file_info->rpaths,
+ executablePath);
}
bool cmBinUtilsMacOSMachOLinker::ScanDependencies(
@@ -98,14 +120,16 @@ bool cmBinUtilsMacOSMachOLinker::GetFileDependencies(
!IsMissingSystemDylib(path)) {
auto filename = cmSystemTools::GetFilenameName(path);
bool unique;
- std::vector<std::string> libs;
- std::vector<std::string> depRpaths;
- if (!this->Tool->GetFileInfo(path, libs, depRpaths)) {
+ const FileInfo* dep_file_info = this->GetFileInfo(path);
+ if (dep_file_info == nullptr) {
return false;
}
- this->Archive->AddResolvedPath(filename, path, unique, depRpaths);
+
+ this->Archive->AddResolvedPath(filename, path, unique,
+ dep_file_info->rpaths);
if (unique &&
- !this->ScanDependencies(path, libs, depRpaths, executablePath)) {
+ !this->ScanDependencies(path, dep_file_info->libs,
+ dep_file_info->rpaths, executablePath)) {
return false;
}
}
diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h
index eae23cc88..ac1177bb5 100644
--- a/Source/cmBinUtilsMacOSMachOLinker.h
+++ b/Source/cmBinUtilsMacOSMachOLinker.h
@@ -5,6 +5,7 @@
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
#include "cmBinUtilsLinker.h"
@@ -24,7 +25,16 @@ public:
cmStateEnums::TargetType type) override;
private:
+ struct FileInfo
+ {
+ std::vector<std::string> libs;
+ std::vector<std::string> rpaths;
+ };
+
std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool;
+ std::unordered_map<std::string, FileInfo> ScannedFileInfo;
+
+ const FileInfo* GetFileInfo(std::string const& file);
bool ScanDependencies(std::string const& file,
std::vector<std::string> const& libs,
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 56b080aa6..415a12447 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -6,10 +6,10 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
@@ -102,7 +102,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args,
cmMakefile& mf = status.GetMakefile();
std::string const& define = args[0];
- cmProp cacheValue = mf.GetDefinition(define);
+ cmValue cacheValue = mf.GetDefinition(define);
std::string configType;
if (!cmSystemTools::GetEnv("CMAKE_CONFIG_TYPE", configType) ||
diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx
index f9b8f8f5d..20d6089b9 100644
--- a/Source/cmBuildNameCommand.cxx
+++ b/Source/cmBuildNameCommand.cxx
@@ -8,9 +8,9 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
bool cmBuildNameCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -20,7 +20,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args,
return false;
}
cmMakefile& mf = status.GetMakefile();
- cmProp cacheValue = mf.GetDefinition(args[0]);
+ cmValue cacheValue = mf.GetDefinition(args[0]);
if (cacheValue) {
// do we need to correct the value?
cmsys::RegularExpression reg("[()/]");
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 055056887..3922c565a 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -2,214 +2,517 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCMakeHostSystemInformationCommand.h"
-#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <cm/optional>
+#include <cm/string_view>
+#include <cmext/string_view>
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
#include "cmsys/SystemInformation.hxx"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
-#if defined(_WIN32)
+#ifdef _WIN32
# include "cmAlgorithms.h"
# include "cmGlobalGenerator.h"
+# include "cmGlobalVisualStudio10Generator.h"
# include "cmGlobalVisualStudioVersionedGenerator.h"
-# include "cmSystemTools.h"
# include "cmVSSetupHelper.h"
# define HAVE_VS_SETUP_HELPER
#endif
namespace {
-bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
- std::string const& key, std::string& value);
-std::string ValueToString(size_t value);
-std::string ValueToString(const char* value);
-std::string ValueToString(std::string const& value);
-}
+std::string const DELIM[2] = { {}, ";" };
-// cmCMakeHostSystemInformation
-bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
- cmExecutionStatus& status)
+// BEGIN Private functions
+std::string ValueToString(std::size_t const value)
{
- size_t current_index = 0;
-
- if (args.size() < (current_index + 2) || args[current_index] != "RESULT") {
- status.SetError("missing RESULT specification.");
- return false;
- }
-
- std::string const& variable = args[current_index + 1];
- current_index += 2;
-
- if (args.size() < (current_index + 2) || args[current_index] != "QUERY") {
- status.SetError("missing QUERY specification");
- return false;
- }
-
- cmsys::SystemInformation info;
- info.RunCPUCheck();
- info.RunOSCheck();
- info.RunMemoryCheck();
-
- std::string result_list;
- for (size_t i = current_index + 1; i < args.size(); ++i) {
- std::string const& key = args[i];
- if (i != current_index + 1) {
- result_list += ";";
- }
- std::string value;
- if (!GetValue(status, info, key, value)) {
- return false;
- }
- result_list += value;
- }
-
- status.GetMakefile().AddDefinition(variable, result_list);
+ return std::to_string(value);
+}
- return true;
+std::string ValueToString(const char* const value)
+{
+ return value ? value : std::string{};
}
-namespace {
+std::string ValueToString(std::string const& value)
+{
+ return value;
+}
-bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info,
- std::string const& key, std::string& value)
+cm::optional<std::string> GetValue(cmsys::SystemInformation& info,
+ std::string const& key)
{
- if (key == "NUMBER_OF_LOGICAL_CORES") {
- value = ValueToString(info.GetNumberOfLogicalCPU());
- } else if (key == "NUMBER_OF_PHYSICAL_CORES") {
- value = ValueToString(info.GetNumberOfPhysicalCPU());
- } else if (key == "HOSTNAME") {
- value = ValueToString(info.GetHostname());
- } else if (key == "FQDN") {
- value = ValueToString(info.GetFullyQualifiedDomainName());
- } else if (key == "TOTAL_VIRTUAL_MEMORY") {
- value = ValueToString(info.GetTotalVirtualMemory());
- } else if (key == "AVAILABLE_VIRTUAL_MEMORY") {
- value = ValueToString(info.GetAvailableVirtualMemory());
- } else if (key == "TOTAL_PHYSICAL_MEMORY") {
- value = ValueToString(info.GetTotalPhysicalMemory());
- } else if (key == "AVAILABLE_PHYSICAL_MEMORY") {
- value = ValueToString(info.GetAvailablePhysicalMemory());
- } else if (key == "IS_64BIT") {
- value = ValueToString(info.Is64Bits());
- } else if (key == "HAS_FPU") {
- value = ValueToString(
+ if (key == "NUMBER_OF_LOGICAL_CORES"_s) {
+ return ValueToString(info.GetNumberOfLogicalCPU());
+ }
+ if (key == "NUMBER_OF_PHYSICAL_CORES"_s) {
+ return ValueToString(info.GetNumberOfPhysicalCPU());
+ }
+ if (key == "HOSTNAME"_s) {
+ return ValueToString(info.GetHostname());
+ }
+ if (key == "FQDN"_s) {
+ return ValueToString(info.GetFullyQualifiedDomainName());
+ }
+ if (key == "TOTAL_VIRTUAL_MEMORY"_s) {
+ return ValueToString(info.GetTotalVirtualMemory());
+ }
+ if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) {
+ return ValueToString(info.GetAvailableVirtualMemory());
+ }
+ if (key == "TOTAL_PHYSICAL_MEMORY"_s) {
+ return ValueToString(info.GetTotalPhysicalMemory());
+ }
+ if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) {
+ return ValueToString(info.GetAvailablePhysicalMemory());
+ }
+ if (key == "IS_64BIT"_s) {
+ return ValueToString(info.Is64Bits());
+ }
+ if (key == "HAS_FPU"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU));
- } else if (key == "HAS_MMX") {
- value = ValueToString(
+ }
+ if (key == "HAS_MMX"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX));
- } else if (key == "HAS_MMX_PLUS") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_MMX_PLUS"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS));
- } else if (key == "HAS_SSE") {
- value = ValueToString(
+ }
+ if (key == "HAS_SSE"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE));
- } else if (key == "HAS_SSE2") {
- value = ValueToString(
+ }
+ if (key == "HAS_SSE2"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2));
- } else if (key == "HAS_SSE_FP") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SSE_FP"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SSE_FP));
- } else if (key == "HAS_SSE_MMX") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SSE_MMX"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SSE_MMX));
- } else if (key == "HAS_AMD_3DNOW") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_AMD_3DNOW"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW));
- } else if (key == "HAS_AMD_3DNOW_PLUS") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_AMD_3DNOW_PLUS"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS));
- } else if (key == "HAS_IA64") {
- value = ValueToString(
+ }
+ if (key == "HAS_IA64"_s) {
+ return ValueToString(
info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64));
- } else if (key == "HAS_SERIAL_NUMBER") {
- value = ValueToString(info.DoesCPUSupportFeature(
+ }
+ if (key == "HAS_SERIAL_NUMBER"_s) {
+ return ValueToString(info.DoesCPUSupportFeature(
cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER));
- } else if (key == "PROCESSOR_NAME") {
- value = ValueToString(info.GetExtendedProcessorName());
- } else if (key == "PROCESSOR_DESCRIPTION") {
- value = info.GetCPUDescription();
- } else if (key == "PROCESSOR_SERIAL_NUMBER") {
- value = ValueToString(info.GetProcessorSerialNumber());
- } else if (key == "OS_NAME") {
- value = ValueToString(info.GetOSName());
- } else if (key == "OS_RELEASE") {
- value = ValueToString(info.GetOSRelease());
- } else if (key == "OS_VERSION") {
- value = ValueToString(info.GetOSVersion());
- } else if (key == "OS_PLATFORM") {
- value = ValueToString(info.GetOSPlatform());
-#ifdef HAVE_VS_SETUP_HELPER
- } else if (key == "VS_15_DIR") {
- // If generating for the VS 15 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs15gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs15gen->GetVSInstance(value)) {
- return true;
- }
+ }
+ if (key == "PROCESSOR_NAME"_s) {
+ return ValueToString(info.GetExtendedProcessorName());
+ }
+ if (key == "PROCESSOR_DESCRIPTION"_s) {
+ return info.GetCPUDescription();
+ }
+ if (key == "PROCESSOR_SERIAL_NUMBER"_s) {
+ return ValueToString(info.GetProcessorSerialNumber());
+ }
+ if (key == "OS_NAME"_s) {
+ return ValueToString(info.GetOSName());
+ }
+ if (key == "OS_RELEASE"_s) {
+ return ValueToString(info.GetOSRelease());
+ }
+ if (key == "OS_VERSION"_s) {
+ return ValueToString(info.GetOSVersion());
+ }
+ if (key == "OS_PLATFORM"_s) {
+ return ValueToString(info.GetOSPlatform());
+ }
+ return {};
+}
+
+cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine(
+ std::string const& line)
+{
+ std::string key;
+ std::string value;
+
+ char prev = 0;
+ enum ParserState
+ {
+ PARSE_KEY_1ST,
+ PARSE_KEY,
+ FOUND_EQ,
+ PARSE_SINGLE_QUOTE_VALUE,
+ PARSE_DBL_QUOTE_VALUE,
+ PARSE_VALUE,
+ IGNORE_REST
+ } state = PARSE_KEY_1ST;
+
+ for (auto ch : line) {
+ switch (state) {
+ case PARSE_KEY_1ST:
+ if (std::isalpha(ch) || ch == '_') {
+ key += ch;
+ state = PARSE_KEY;
+ } else if (!std::isspace(ch)) {
+ state = IGNORE_REST;
+ }
+ break;
+
+ case PARSE_KEY:
+ if (ch == '=') {
+ state = FOUND_EQ;
+ } else if (std::isalnum(ch) || ch == '_') {
+ key += ch;
+ } else {
+ state = IGNORE_REST;
+ }
+ break;
+
+ case FOUND_EQ:
+ switch (ch) {
+ case '\'':
+ state = PARSE_SINGLE_QUOTE_VALUE;
+ break;
+ case '"':
+ state = PARSE_DBL_QUOTE_VALUE;
+ break;
+ case '#':
+ case '\\':
+ state = IGNORE_REST;
+ break;
+ default:
+ value += ch;
+ state = PARSE_VALUE;
+ }
+ break;
+
+ case PARSE_SINGLE_QUOTE_VALUE:
+ if (ch == '\'') {
+ if (prev != '\\') {
+ state = IGNORE_REST;
+ } else {
+ assert(!value.empty());
+ value[value.size() - 1] = ch;
+ }
+ } else {
+ value += ch;
+ }
+ break;
+
+ case PARSE_DBL_QUOTE_VALUE:
+ if (ch == '"') {
+ if (prev != '\\') {
+ state = IGNORE_REST;
+ } else {
+ assert(!value.empty());
+ value[value.size() - 1] = ch;
+ }
+ } else {
+ value += ch;
+ }
+ break;
+
+ case PARSE_VALUE:
+ if (ch == '#' || std::isspace(ch)) {
+ state = IGNORE_REST;
+ } else {
+ value += ch;
+ }
+ break;
+
+ default:
+ // Unexpected os-release parser state!
+ state = IGNORE_REST;
+ break;
}
- // Otherwise, find a VS 15 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(15);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ if (state == IGNORE_REST) {
+ break;
}
- } else if (key == "VS_16_DIR") {
- // If generating for the VS 16 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs16gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs16gen->GetVSInstance(value)) {
- return true;
+ prev = ch;
+ }
+ if (!(key.empty() || value.empty())) {
+ return std::make_pair(key, value);
+ }
+ return {};
+}
+
+std::map<std::string, std::string> GetOSReleaseVariables(
+ cmExecutionStatus& status)
+{
+ auto& makefile = status.GetMakefile();
+ const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT");
+
+ std::map<std::string, std::string> data;
+ // Based on
+ // https://www.freedesktop.org/software/systemd/man/os-release.html
+ for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) {
+ const auto& filename = cmStrCat(sysroot, name);
+ if (cmSystemTools::FileExists(filename)) {
+ cmsys::ifstream fin(filename.c_str());
+ for (std::string line; !std::getline(fin, line).fail();) {
+ auto kv = ParseOSReleaseLine(line);
+ if (kv.has_value()) {
+ data.emplace(kv.value());
+ }
}
+ break;
+ }
+ }
+ // Got smth?
+ if (!data.empty()) {
+ return data;
+ }
+
+ // Ugh, it could be some pre-os-release distro.
+ // Lets try some fallback getters.
+ // See also:
+ // - http://linuxmafia.com/faq/Admin/release-files.html
+
+ // 1. CMake provided
+ cmsys::Glob gl;
+ std::vector<std::string> scripts;
+ auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(),
+ "/Modules/Internal/OSRelease/*.cmake");
+ if (gl.FindFiles(findExpr)) {
+ scripts = gl.GetFiles();
+ }
+
+ // 2. User provided (append to the CMake prvided)
+ makefile.GetDefExpandList("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS", scripts);
+
+ // Filter out files that are not in format `NNN-name.cmake`
+ auto checkName = [](std::string const& filepath) -> bool {
+ auto const& filename = cmSystemTools::GetFilenameName(filepath);
+ // NOTE Minimum filename length expected:
+ // NNN-<at-least-one-char-name>.cmake --> 11
+ return (filename.size() < 11) || !std::isdigit(filename[0]) ||
+ !std::isdigit(filename[1]) || !std::isdigit(filename[2]) ||
+ filename[3] != '-';
+ };
+ scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName),
+ scripts.end());
+
+ // Make sure scripts are running in desired order
+ std::sort(scripts.begin(), scripts.end(),
+ [](std::string const& lhs, std::string const& rhs) -> bool {
+ long lhs_order;
+ cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u),
+ &lhs_order);
+ long rhs_order;
+ cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u),
+ &rhs_order);
+ return lhs_order < rhs_order;
+ });
+
+ // Name of the variable to put the results
+ auto const result_variable = "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT"_s;
+
+ for (auto const& script : scripts) {
+ // Unset the result variable
+ makefile.RemoveDefinition(result_variable.data());
+
+ // include FATAL_ERROR and ERROR in the return status
+ if (!makefile.ReadListFile(script) ||
+ cmSystemTools::GetErrorOccuredFlag()) {
+ // Ok, no worries... go try the next script.
+ continue;
}
- // Otherwise, find a VS 16 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(16);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ std::vector<std::string> variables;
+ if (!makefile.GetDefExpandList(result_variable.data(), variables)) {
+ // Heh, this script didn't found anything... go try the next one.
+ continue;
}
- } else if (key == "VS_17_DIR") {
- // If generating for the VS 17 IDE, use the same instance.
- cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
- if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) {
- cmGlobalVisualStudioVersionedGenerator* vs17gen =
- static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
- if (vs17gen->GetVSInstance(value)) {
- return true;
+
+ for (auto const& variable : variables) {
+ auto value = makefile.GetSafeDefinition(variable);
+ makefile.RemoveDefinition(variable);
+
+ if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) {
+ // Ignore unknown variable set by the script
+ continue;
}
+
+ auto key = variable.substr(result_variable.size() + 1,
+ variable.size() - result_variable.size() - 1);
+ data.emplace(std::move(key), std::move(value));
}
- // Otherwise, find a VS 17 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(17);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ // Try 'till some script can get anything
+ if (!data.empty()) {
+ data.emplace("USED_FALLBACK_SCRIPT", script);
+ break;
}
-#endif
- } else {
- std::string e = "does not recognize <key> " + key;
- status.SetError(e);
- return false;
}
- return true;
+ makefile.RemoveDefinition(result_variable.data());
+
+ return data;
}
-std::string ValueToString(size_t value)
+cm::optional<std::string> GetValue(cmExecutionStatus& status,
+ std::string const& key,
+ std::string const& variable)
{
- return std::to_string(value);
+ const auto prefix = "DISTRIB_"_s;
+ if (!cmHasPrefix(key, prefix)) {
+ return {};
+ }
+
+ static const std::map<std::string, std::string> s_os_release =
+ GetOSReleaseVariables(status);
+
+ auto& makefile = status.GetMakefile();
+
+ const std::string subkey =
+ key.substr(prefix.size(), key.size() - prefix.size());
+ if (subkey == "INFO"_s) {
+ std::string vars;
+ for (const auto& kv : s_os_release) {
+ auto cmake_var_name = cmStrCat(variable, '_', kv.first);
+ vars += DELIM[!vars.empty()] + cmake_var_name;
+ makefile.AddDefinition(cmake_var_name, kv.second);
+ }
+ return cm::optional<std::string>(std::move(vars));
+ }
+
+ // Query individual variable
+ const auto it = s_os_release.find(subkey);
+ if (it != s_os_release.cend()) {
+ return it->second;
+ }
+
+ // NOTE Empty string means requested variable not set
+ return std::string{};
}
-std::string ValueToString(const char* value)
+#ifdef HAVE_VS_SETUP_HELPER
+cm::optional<std::string> GetValue(cmExecutionStatus& status,
+ std::string const& key)
{
- std::string safe_string = value ? value : "";
- return safe_string;
+ auto* const gg = status.GetMakefile().GetGlobalGenerator();
+ for (auto vs : { 15, 16, 17 }) {
+ if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) {
+ std::string value;
+ // If generating for the VS nn IDE, use the same instance.
+
+ if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) {
+ cmGlobalVisualStudioVersionedGenerator* vsNNgen =
+ static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg);
+ if (vsNNgen->GetVSInstance(value)) {
+ return value;
+ }
+ }
+
+ // Otherwise, find a VS nn instance ourselves.
+ cmVSSetupAPIHelper vsSetupAPIHelper(vs);
+ if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
+ cmSystemTools::ConvertToUnixSlashes(value);
+ }
+ return value;
+ }
+ }
+
+ if (key == "VS_MSBUILD_COMMAND"_s && gg->IsVisualStudioAtLeast10()) {
+ cmGlobalVisualStudio10Generator* vs10gen =
+ static_cast<cmGlobalVisualStudio10Generator*>(gg);
+ return vs10gen->FindMSBuildCommandEarly(&status.GetMakefile());
+ }
+
+ return {};
}
+#endif
-std::string ValueToString(std::string const& value)
+cm::optional<std::string> GetValueChained()
{
- return value;
+ return {};
}
+
+template <typename GetterFn, typename... Next>
+cm::optional<std::string> GetValueChained(GetterFn current, Next... chain)
+{
+ auto value = current();
+ if (value.has_value()) {
+ return value;
+ }
+ return GetValueChained(chain...);
+}
+// END Private functions
+} // anonymous namespace
+
+// cmCMakeHostSystemInformation
+bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args,
+ cmExecutionStatus& status)
+{
+ std::size_t current_index = 0;
+
+ if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) {
+ status.SetError("missing RESULT specification.");
+ return false;
+ }
+
+ auto const& variable = args[current_index + 1];
+ current_index += 2;
+
+ if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) {
+ status.SetError("missing QUERY specification");
+ return false;
+ }
+
+ static cmsys::SystemInformation info;
+ static auto initialized = false;
+ if (!initialized) {
+ info.RunCPUCheck();
+ info.RunOSCheck();
+ info.RunMemoryCheck();
+ initialized = true;
+ }
+
+ std::string result_list;
+ for (auto i = current_index + 1; i < args.size(); ++i) {
+ result_list += DELIM[!result_list.empty()];
+
+ auto const& key = args[i];
+ // clang-format off
+ auto value =
+ GetValueChained(
+ [&]() { return GetValue(info, key); }
+ , [&]() { return GetValue(status, key, variable); }
+#ifdef HAVE_VS_SETUP_HELPER
+ , [&]() { return GetValue(status, key); }
+#endif
+ );
+ // clang-format on
+ if (!value) {
+ status.SetError("does not recognize <key> " + key);
+ return false;
+ }
+ result_list += value.value();
+ }
+
+ status.GetMakefile().AddDefinition(variable, result_list);
+
+ return true;
}
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index 9a5fa7bfc..bf94c2dce 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -18,11 +18,11 @@
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
// Helper classes for argument parsing
@@ -150,7 +150,7 @@ public:
bool getInputPath(const std::string& arg, cmExecutionStatus& status,
std::string& path)
{
- cmProp def = status.GetMakefile().GetDefinition(arg);
+ cmValue def = status.GetMakefile().GetDefinition(arg);
if (!def) {
status.SetError("undefined variable for input path.");
return false;
diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 1f9904364..ebf639b74 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -9,6 +9,7 @@
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
namespace {
bool HandleSetMode(std::vector<std::string> const& args,
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index ace73825a..e46003117 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -140,7 +140,7 @@ const char* CCONV cmGetCurrentOutputDirectory(void* arg)
const char* CCONV cmGetDefinition(void* arg, const char* def)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return cmToCStr(mf->GetDefinition(def));
+ return mf->GetDefinition(def).GetCStr();
}
int CCONV cmIsOn(void* arg, const char* name)
@@ -173,7 +173,7 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
std::string(tgt) + " for directory " + std::string(d));
return;
}
- t->InsertLinkDirectory(d, mf->GetBacktrace());
+ t->InsertLinkDirectory(BT<std::string>(d, mf->GetBacktrace()));
}
void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
@@ -592,12 +592,12 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop)
{
cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
if (cmSourceFile* rsf = sf->RealSourceFile) {
- return cmToCStr(rsf->GetProperty(prop));
+ return rsf->GetProperty(prop).GetCStr();
}
if (!strcmp(prop, "LOCATION")) {
return sf->FullPath.c_str();
}
- return cmToCStr(sf->Properties.GetPropertyValue(prop));
+ return sf->Properties.GetPropertyValue(prop).GetCStr();
}
int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop)
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 7c469c84a..dfd2b6c34 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -56,12 +56,12 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmProcessOutput.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
#include "cmXMLWriter.h"
@@ -1457,11 +1457,11 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml)
return;
}
// This code should go when cdash is changed to use labels only
- cmProp subproject = cm->GetState()->GetGlobalProperty("SubProject");
+ cmValue subproject = cm->GetState()->GetGlobalProperty("SubProject");
if (subproject) {
xml.StartElement("Subproject");
xml.Attribute("name", *subproject);
- cmProp labels =
+ cmValue labels =
ch->GetCMake()->GetState()->GetGlobalProperty("SubProjectLabels");
if (labels) {
xml.StartElement("Labels");
@@ -1475,7 +1475,7 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml)
}
// This code should stay when cdash only does label based sub-projects
- cmProp label = cm->GetState()->GetGlobalProperty("Label");
+ cmValue label = cm->GetState()->GetGlobalProperty("Label");
if (label) {
xml.StartElement("Labels");
xml.Element("Label", *label);
@@ -2425,7 +2425,7 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName,
case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
Extra:
this->Impl->ExtraVerbose = true;
- // intentional fallthrough
+ CM_FALLTHROUGH;
case cmCMakePresetsFile::TestPreset::OutputOptions::VerbosityEnum::
Verbose:
this->Impl->Verbose = true;
@@ -3056,7 +3056,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const std::string& dir,
void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def,
std::vector<std::string>& vec)
{
- cmProp dval = mf->GetDefinition(def);
+ cmValue dval = mf->GetDefinition(def);
if (!dval) {
return;
}
@@ -3073,7 +3073,7 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def,
void cmCTest::PopulateCustomInteger(cmMakefile* mf, const std::string& def,
int& val)
{
- cmProp dval = mf->GetDefinition(def);
+ cmValue dval = mf->GetDefinition(def);
if (!dval) {
return;
}
@@ -3407,7 +3407,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
cmMakefile* mf, const char* dconfig, const std::string& cmake_var,
bool suppress)
{
- cmProp ctvar = mf->GetDefinition(cmake_var);
+ cmValue ctvar = mf->GetDefinition(cmake_var);
if (!ctvar) {
return false;
}
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 1a950dfb0..b9d1f66d2 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -118,13 +118,13 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
}
this->CacheMajorVersion = 0;
this->CacheMinorVersion = 0;
- if (cmProp cmajor =
+ if (cmValue cmajor =
this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
unsigned int v = 0;
if (sscanf(cmajor->c_str(), "%u", &v) == 1) {
this->CacheMajorVersion = v;
}
- if (cmProp cminor =
+ if (cmValue cminor =
this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
if (sscanf(cminor->c_str(), "%u", &v) == 1) {
this->CacheMinorVersion = v;
@@ -144,7 +144,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
}
// check to make sure the cache directory has not
// been moved
- cmProp oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ cmValue oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
if (internal && oldDir) {
std::string currentcwd = path;
std::string oldcwd = *oldDir;
@@ -152,7 +152,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- cmProp dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
+ cmValue dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
std::ostringstream message;
message << "The current CMakeCache.txt directory " << currentcwd
<< " is different than the directory " << (dir ? *dir : "")
@@ -203,7 +203,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os,
cmMessenger* messenger) const
{
for (const char* p : cmCacheManager::PersistentProperties) {
- if (cmProp value = e.GetProperty(p)) {
+ if (cmValue value = e.GetProperty(p)) {
std::string helpstring =
cmStrCat(p, " property for variable: ", entryKey);
cmCacheManager::OutputHelpString(os, helpstring);
@@ -232,17 +232,17 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
// before writing the cache, update the version numbers
// to the
this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION",
- std::to_string(cmVersion::GetMajorVersion()).c_str(),
+ std::to_string(cmVersion::GetMajorVersion()),
"Major version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION",
- std::to_string(cmVersion::GetMinorVersion()).c_str(),
+ std::to_string(cmVersion::GetMinorVersion()),
"Minor version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION",
- std::to_string(cmVersion::GetPatchVersion()).c_str(),
+ std::to_string(cmVersion::GetPatchVersion()),
"Patch version of cmake used to create the "
"current loaded cache",
cmStateEnums::INTERNAL);
@@ -256,7 +256,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a');
}
cmSystemTools::ConvertToUnixSlashes(currentcwd);
- this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(),
+ this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd,
"This is the directory where this CMakeCache.txt"
" was created",
cmStateEnums::INTERNAL);
@@ -296,7 +296,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
*/
} else if (t != cmStateEnums::INTERNAL) {
// Format is key:type=value
- if (cmProp help = ce.GetProperty("HELPSTRING")) {
+ if (cmValue help = ce.GetProperty("HELPSTRING")) {
cmCacheManager::OutputHelpString(fout, *help);
} else {
cmCacheManager::OutputHelpString(fout, "Missing description");
@@ -326,7 +326,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
this->WritePropertyEntries(fout, i.first, i.second, messenger);
if (t == cmStateEnums::INTERNAL) {
// Format is key:type=value
- if (cmProp help = i.second.GetProperty("HELPSTRING")) {
+ if (cmValue help = i.second.GetProperty("HELPSTRING")) {
cmCacheManager::OutputHelpString(fout, *help);
}
cmCacheManager::OutputKey(fout, i.first);
@@ -496,11 +496,11 @@ const cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
return nullptr;
}
-cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const
+cmValue cmCacheManager::GetInitializedCacheValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
if (entry->Initialized) {
- return &entry->GetValue();
+ return cmValue(entry->GetValue());
}
}
return nullptr;
@@ -521,7 +521,7 @@ void cmCacheManager::PrintCache(std::ostream& out) const
"=================================================\n";
}
-void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
+void cmCacheManager::AddCacheEntry(const std::string& key, cmValue value,
const char* helpString,
cmStateEnums::CacheEntryType type)
{
@@ -550,10 +550,10 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value,
: "(This variable does not exist and should not be used)");
}
-void cmCacheManager::CacheEntry::SetValue(const char* value)
+void cmCacheManager::CacheEntry::SetValue(cmValue value)
{
if (value) {
- this->Value = value;
+ this->Value = *value;
this->Initialized = true;
} else {
this->Value.clear();
@@ -565,13 +565,13 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
return this->Properties.GetKeys();
}
-cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
+cmValue cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
{
if (prop == "TYPE") {
- return &cmState::CacheEntryTypeToString(this->Type);
+ return cmValue(cmState::CacheEntryTypeToString(this->Type));
}
if (prop == "VALUE") {
- return &this->Value;
+ return cmValue(this->Value);
}
return this->Properties.GetPropertyValue(prop);
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 7a9a7dc41..bc3fb510a 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -11,9 +11,9 @@
#include <utility>
#include <vector>
-#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
class cmMessenger;
@@ -31,13 +31,13 @@ class cmCacheManager
public:
const std::string& GetValue() const { return this->Value; }
- void SetValue(const char*);
+ void SetValue(cmValue);
cmStateEnums::CacheEntryType GetType() const { return this->Type; }
void SetType(cmStateEnums::CacheEntryType ty) { this->Type = ty; }
std::vector<std::string> GetPropertyList() const;
- cmProp GetProperty(const std::string& property) const;
+ cmValue GetProperty(const std::string& property) const;
bool GetPropertyAsBool(const std::string& property) const;
void SetProperty(const std::string& property, const char* value);
void SetProperty(const std::string& property, bool value);
@@ -70,12 +70,12 @@ public:
bool IsCacheLoaded() const { return this->CacheLoaded; }
//! Get a value from the cache given a key
- cmProp GetInitializedCacheValue(const std::string& key) const;
+ cmValue GetInitializedCacheValue(const std::string& key) const;
- cmProp GetCacheEntryValue(const std::string& key) const
+ cmValue GetCacheEntryValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
- return &entry->GetValue();
+ return cmValue(entry->GetValue());
}
return nullptr;
}
@@ -83,7 +83,7 @@ public:
void SetCacheEntryValue(std::string const& key, std::string const& value)
{
if (auto* entry = this->GetCacheEntry(key)) {
- entry->SetValue(value.c_str());
+ entry->SetValue(cmValue(value));
}
}
@@ -104,8 +104,8 @@ public:
return {};
}
- cmProp GetCacheEntryProperty(std::string const& key,
- std::string const& propName) const
+ cmValue GetCacheEntryProperty(std::string const& key,
+ std::string const& propName) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
return entry->GetProperty(propName);
@@ -173,6 +173,18 @@ public:
//! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key,
+ value ? cmValue(std::string(value)) : cmValue(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key, cmValue(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmValue value,
const char* helpString,
cmStateEnums::CacheEntryType type);
diff --git a/Source/cmCommand.h b/Source/cmCommand.h
index 68c56d90c..f5a519022 100644
--- a/Source/cmCommand.h
+++ b/Source/cmCommand.h
@@ -44,7 +44,7 @@ public:
cmMakefile* GetMakefile() { return this->Makefile; }
void SetExecutionStatus(cmExecutionStatus* s);
- cmExecutionStatus* GetExecutionStatus() { return this->Status; };
+ cmExecutionStatus* GetExecutionStatus() { return this->Status; }
/**
* This is called by the cmMakefile when the command is first
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index deddba8ef..2ed04e5c4 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -14,10 +14,10 @@
#include "cmCommandArgumentLexer.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
int cmCommandArgument_yyparse(yyscan_t yyscanner);
//
@@ -73,7 +73,8 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
return "";
}
if (strcmp(key, "CACHE") == 0) {
- if (cmProp c = this->Makefile->GetState()->GetInitializedCacheValue(var)) {
+ if (cmValue c =
+ this->Makefile->GetState()->GetInitializedCacheValue(var)) {
if (this->EscapeQuotes) {
return this->AddString(cmEscapeQuotes(*c));
}
@@ -103,7 +104,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
}
return this->AddString(line);
}
- cmProp value = this->Makefile->GetDefinition(var);
+ cmValue value = this->Makefile->GetDefinition(var);
if (!value) {
this->Makefile->MaybeWarnUninitialized(var, this->FileName);
if (!this->RemoveEmpty) {
@@ -113,7 +114,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
if (this->EscapeQuotes && value) {
return this->AddString(cmEscapeQuotes(*value));
}
- return this->AddString(cmToCStrSafe(value));
+ return this->AddString(value);
}
const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 7c2e20c01..8d5ce7ed0 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -14,12 +14,12 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
+#include "cmValue.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
: GeneratorTarget(gt)
@@ -39,10 +39,10 @@ std::vector<std::string> const& cmCommonTargetGenerator::GetConfigNames() const
return this->ConfigNames;
}
-const char* cmCommonTargetGenerator::GetFeature(const std::string& feature,
- const std::string& config)
+cmValue cmCommonTargetGenerator::GetFeature(const std::string& feature,
+ const std::string& config)
{
- return this->GeneratorTarget->GetFeature(feature, config)->c_str();
+ return this->GeneratorTarget->GetFeature(feature, config);
}
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
@@ -56,7 +56,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
}
// TODO: Create a per-language flag variable.
- cmProp defFileFlag =
+ cmValue defFileFlag =
this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
if (!defFileFlag) {
return;
@@ -240,11 +240,16 @@ std::string cmCommonTargetGenerator::GetManifests(const std::string& config)
std::vector<std::string> manifests;
manifests.reserve(manifest_srcs.size());
+
+ std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
+ std::string const& manifestFlag =
+ this->Makefile->GetDefinition("CMAKE_" + lang + "_LINKER_MANIFEST_FLAG");
for (cmSourceFile const* manifest_src : manifest_srcs) {
- manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat(
- this->LocalCommonGenerator->MaybeRelativeToWorkDir(
- manifest_src->GetFullPath()),
- cmOutputConverter::SHELL));
+ manifests.push_back(manifestFlag +
+ this->LocalCommonGenerator->ConvertToOutputFormat(
+ this->LocalCommonGenerator->MaybeRelativeToWorkDir(
+ manifest_src->GetFullPath()),
+ cmOutputConverter::SHELL));
}
return cmJoin(manifests, " ");
@@ -254,7 +259,7 @@ std::string cmCommonTargetGenerator::GetAIXExports(std::string const&)
{
std::string aixExports;
if (this->GeneratorTarget->Target->IsAIX()) {
- if (cmProp exportAll =
+ if (cmValue exportAll =
this->GeneratorTarget->GetProperty("AIX_EXPORT_ALL_SYMBOLS")) {
if (cmIsOff(*exportAll)) {
aixExports = "-n";
@@ -270,7 +275,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
{
// Lookup the flag to specify the version.
std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
- cmProp flag = this->Makefile->GetDefinition(fvar);
+ cmValue flag = this->Makefile->GetDefinition(fvar);
// Skip if no such flag.
if (!flag) {
@@ -297,7 +302,7 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher(
const std::string& config)
{
std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
- cmProp launcherProp =
+ cmValue launcherProp =
this->GeneratorTarget->GetProperty(lang + "_LINKER_LAUNCHER");
if (cmNonempty(launcherProp)) {
// Convert ;-delimited list to single string
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index a156a41af..baa36c9e2 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "cmValue.h"
+
class cmGeneratorTarget;
class cmGlobalCommonGenerator;
class cmLinkLineComputer;
@@ -28,8 +30,7 @@ public:
protected:
// Feature query methods.
- const char* GetFeature(const std::string& feature,
- const std::string& config);
+ cmValue GetFeature(const std::string& feature, const std::string& config);
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
@@ -40,6 +41,7 @@ protected:
cmLocalCommonGenerator* LocalCommonGenerator;
cmGlobalCommonGenerator* GlobalCommonGenerator;
std::vector<std::string> ConfigNames;
+ bool UseLWYU = false;
void AppendFortranFormatFlags(std::string& flags,
cmSourceFile const& source);
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 0b27e34c2..370ddff5c 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -18,11 +18,11 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
/*
@@ -322,7 +322,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
} else {
// Look for an old-style <item>_LIB_DEPENDS variable.
std::string var = cmStrCat(entry.Item.Value, "_LIB_DEPENDS");
- if (cmProp val = this->Makefile->GetDefinition(var)) {
+ if (cmValue val = this->Makefile->GetDefinition(var)) {
// The item dependencies are known. Follow them.
BFSEntry qe = { index, val->c_str() };
this->BFSQueue.push(qe);
@@ -489,7 +489,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
// lower.
if (!haveLLT) {
std::string var = cmStrCat(d, "_LINK_TYPE");
- if (cmProp val = this->Makefile->GetDefinition(var)) {
+ if (cmValue val = this->Makefile->GetDefinition(var)) {
if (*val == "debug") {
llt = DEBUG_LibraryType;
} else if (*val == "optimized") {
@@ -607,7 +607,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
from = depender;
}
}
- return from->ResolveLinkItem(name, cmListFileBacktrace());
+ return from->ResolveLinkItem(BT<std::string>(name));
}
void cmComputeLinkDepends::InferDependencies()
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index d15da0c96..831a81fd2 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -20,12 +20,12 @@
#include "cmOrderDirectories.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
//#define CM_COMPUTE_LINK_INFO_DEBUG
@@ -278,38 +278,36 @@ cmComputeLinkInformation::cmComputeLinkInformation(
// On platforms without import libraries there may be a special flag
// to use when creating a plugin (module) that obtains symbols from
// the program that will load it.
- this->LoaderFlag = nullptr;
if (!this->Target->IsDLLPlatform() &&
this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string loader_flag_var =
cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG");
- this->LoaderFlag =
- cmToCStr(this->Makefile->GetDefinition(loader_flag_var));
+ this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var);
}
// Get options needed to link libraries.
- if (cmProp flag = this->Makefile->GetDefinition(
+ if (cmValue flag = this->Makefile->GetDefinition(
"CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FLAG")) {
this->LibLinkFlag = *flag;
} else {
this->LibLinkFlag =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
}
- if (cmProp flag = this->Makefile->GetDefinition(
+ if (cmValue flag = this->Makefile->GetDefinition(
"CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FILE_FLAG")) {
this->LibLinkFileFlag = *flag;
} else {
this->LibLinkFileFlag =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG");
}
- if (cmProp suffix = this->Makefile->GetDefinition(
+ if (cmValue suffix = this->Makefile->GetDefinition(
"CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_SUFFIX")) {
this->LibLinkSuffix = *suffix;
} else {
this->LibLinkSuffix =
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
}
- if (cmProp flag = this->Makefile->GetDefinition(
+ if (cmValue flag = this->Makefile->GetDefinition(
"CMAKE_" + this->LinkLanguage + "_LINK_OBJECT_FILE_FLAG")) {
this->ObjLinkFileFlag = *flag;
} else {
@@ -528,7 +526,7 @@ bool cmComputeLinkInformation::Compute()
// Restore the target link type so the correct system runtime
// libraries are found.
- cmProp lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC");
+ cmValue lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC");
if (cmIsOn(lss)) {
this->SetCurrentLinkType(LinkStatic);
} else {
@@ -607,7 +605,7 @@ void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang)
if (runtimeLibrary.empty()) {
return;
}
- if (cmProp runtimeLinkOptions = this->Makefile->GetDefinition(
+ if (cmValue runtimeLinkOptions = this->Makefile->GetDefinition(
"CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + runtimeLibrary)) {
std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions);
for (std::string const& i : libsVec) {
@@ -623,7 +621,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
// Add libraries for this language that are not implied by the
// linker language.
std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES");
- if (cmProp libs = this->Makefile->GetDefinition(libVar)) {
+ if (cmValue libs = this->Makefile->GetDefinition(libVar)) {
std::vector<std::string> libsVec = cmExpandedList(*libs);
for (std::string const& i : libsVec) {
if (!cm::contains(this->ImplicitLinkLibs, i)) {
@@ -635,7 +633,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
// Add linker search paths for this language that are not
// implied by the linker language.
std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES");
- if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) {
+ if (cmValue dirs = this->Makefile->GetDefinition(dirVar)) {
std::vector<std::string> dirsVec = cmExpandedList(*dirs);
this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec);
}
@@ -660,8 +658,7 @@ void cmComputeLinkInformation::AddItem(BT<std::string> const& item,
// This link item is an executable that may provide symbols
// used by this target. A special flag is needed on this
// platform. Add it now.
- std::string linkItem;
- linkItem = this->LoaderFlag;
+ std::string linkItem = this->LoaderFlag;
cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config)
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
@@ -839,8 +836,8 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
this->LinkTypeEnabled = false;
// Lookup link type selection flags.
- cmProp static_link_type_flag = nullptr;
- cmProp shared_link_type_flag = nullptr;
+ cmValue static_link_type_flag = nullptr;
+ cmValue shared_link_type_flag = nullptr;
const char* target_type_str = nullptr;
switch (this->Target->GetType()) {
case cmStateEnums::EXECUTABLE:
@@ -878,7 +875,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
}
// Lookup the starting link type from the target (linked statically?).
- cmProp lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC");
+ cmValue lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC");
this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared;
this->CurrentLinkType = this->StartLinkType;
}
@@ -900,13 +897,14 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
LinkShared);
this->AddLinkExtension(mf->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"),
LinkUnknown);
- if (cmProp linkSuffixes = mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) {
+ if (cmValue linkSuffixes =
+ mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) {
std::vector<std::string> linkSuffixVec = cmExpandedList(*linkSuffixes);
for (std::string const& i : linkSuffixVec) {
this->AddLinkExtension(i, LinkUnknown);
}
}
- if (cmProp sharedSuffixes =
+ if (cmValue sharedSuffixes =
mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) {
std::vector<std::string> sharedSuffixVec = cmExpandedList(*sharedSuffixes);
for (std::string const& i : sharedSuffixVec) {
@@ -1187,6 +1185,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
this->CMP0060WarnItems.insert(item);
}
}
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
@@ -1456,8 +1455,10 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
this->Target->GetBacktrace());
}
}
- case cmPolicies::OLD:
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD: // NOLINT(bugprone-branch-clone)
// OLD behavior does not warn.
+ break;
case cmPolicies::NEW:
// NEW behavior will not get here.
break;
@@ -1496,6 +1497,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
this->CMakeInstance->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
}
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to add the paths containing libraries with
// known full paths as link directories.
@@ -1592,7 +1594,7 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
// Append library architecture to all implicit platform directories
// and add them to the set
- if (cmProp libraryArch =
+ if (cmValue libraryArch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
for (std::string const& i : implicitDirVec) {
this->ImplicitLinkDirs.insert(i + "/" + *libraryArch);
@@ -1785,13 +1787,13 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
}
if (use_build_rpath || use_link_rpath) {
std::string rootPath;
- if (cmProp sysrootLink =
+ if (cmValue sysrootLink =
this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
rootPath = *sysrootLink;
} else {
rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
- cmProp stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
+ cmValue stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
std::string const& installPrefix =
this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
cmSystemTools::ConvertToUnixSlashes(rootPath);
@@ -1859,7 +1861,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
"CMAKE_" + li + "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
if (this->Makefile->IsOn(useVar)) {
std::string dirVar = "CMAKE_" + li + "_IMPLICIT_LINK_DIRECTORIES";
- if (cmProp dirs = this->Makefile->GetDefinition(dirVar)) {
+ if (cmValue dirs = this->Makefile->GetDefinition(dirVar)) {
cmCLI_ExpandListUnique(*dirs, runtimeDirs, emitted);
}
}
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 7fe30b3bb..90a699ebb 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -14,6 +14,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmListFileCache.h"
+#include "cmValue.h"
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -137,7 +138,7 @@ private:
SharedDepModeLink // List file on link line
};
- const char* LoaderFlag;
+ cmValue LoaderFlag;
std::string LibLinkFlag;
std::string LibLinkFileFlag;
std::string ObjLinkFileFlag;
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 76712f4eb..ef89c8b5c 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -17,16 +17,15 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmValue.h"
#include "cmake.h"
/*
@@ -323,7 +322,7 @@ void cmComputeTargetDepends::AddObjectDepends(int depender_index,
}
cmGeneratorTarget const* depender = this->Targets[depender_index];
cmLinkItem const& objItem =
- depender->ResolveLinkItem(objLib, cmListFileBacktrace());
+ depender->ResolveLinkItem(BT<std::string>(objLib));
if (emitted.insert(objItem).second) {
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
@@ -360,6 +359,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n";
issueMessage = true;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::NEW:
@@ -367,6 +367,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
case cmPolicies::REQUIRED_ALWAYS:
issueMessage = true;
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (issueMessage) {
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
@@ -469,7 +470,7 @@ void cmComputeTargetDepends::ComputeIntermediateGraph()
gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
intermediateEdges = initialEdges;
} else {
- if (cmProp optimizeDependencies =
+ if (cmValue optimizeDependencies =
gt->GetProperty("OPTIMIZE_DEPENDENCIES")) {
if (cmIsOn(optimizeDependencies)) {
this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges);
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index f99592cc0..8e479c545 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -2,58 +2,207 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmConditionEvaluator.h"
+#include <array>
#include <cstdio>
#include <cstdlib>
#include <functional>
+#include <iterator>
+#include <list>
#include <sstream>
#include <utility>
+#include <cm/string_view>
#include <cmext/algorithm>
#include "cmsys/RegularExpression.hxx"
+#include "cmExpandedCommandArgument.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
-class cmTest;
-
-static std::string const keyAND = "AND";
-static std::string const keyCOMMAND = "COMMAND";
-static std::string const keyDEFINED = "DEFINED";
-static std::string const keyEQUAL = "EQUAL";
-static std::string const keyEXISTS = "EXISTS";
-static std::string const keyGREATER = "GREATER";
-static std::string const keyGREATER_EQUAL = "GREATER_EQUAL";
-static std::string const keyIN_LIST = "IN_LIST";
-static std::string const keyIS_ABSOLUTE = "IS_ABSOLUTE";
-static std::string const keyIS_DIRECTORY = "IS_DIRECTORY";
-static std::string const keyIS_NEWER_THAN = "IS_NEWER_THAN";
-static std::string const keyIS_SYMLINK = "IS_SYMLINK";
-static std::string const keyLESS = "LESS";
-static std::string const keyLESS_EQUAL = "LESS_EQUAL";
-static std::string const keyMATCHES = "MATCHES";
-static std::string const keyNOT = "NOT";
-static std::string const keyOR = "OR";
-static std::string const keyParenL = "(";
-static std::string const keyParenR = ")";
-static std::string const keyPOLICY = "POLICY";
-static std::string const keySTREQUAL = "STREQUAL";
-static std::string const keySTRGREATER = "STRGREATER";
-static std::string const keySTRGREATER_EQUAL = "STRGREATER_EQUAL";
-static std::string const keySTRLESS = "STRLESS";
-static std::string const keySTRLESS_EQUAL = "STRLESS_EQUAL";
-static std::string const keyTARGET = "TARGET";
-static std::string const keyTEST = "TEST";
-static std::string const keyVERSION_EQUAL = "VERSION_EQUAL";
-static std::string const keyVERSION_GREATER = "VERSION_GREATER";
-static std::string const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL";
-static std::string const keyVERSION_LESS = "VERSION_LESS";
-static std::string const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL";
+namespace {
+auto const keyAND = "AND"_s;
+auto const keyCOMMAND = "COMMAND"_s;
+auto const keyDEFINED = "DEFINED"_s;
+auto const keyEQUAL = "EQUAL"_s;
+auto const keyEXISTS = "EXISTS"_s;
+auto const keyGREATER = "GREATER"_s;
+auto const keyGREATER_EQUAL = "GREATER_EQUAL"_s;
+auto const keyIN_LIST = "IN_LIST"_s;
+auto const keyIS_ABSOLUTE = "IS_ABSOLUTE"_s;
+auto const keyIS_DIRECTORY = "IS_DIRECTORY"_s;
+auto const keyIS_NEWER_THAN = "IS_NEWER_THAN"_s;
+auto const keyIS_SYMLINK = "IS_SYMLINK"_s;
+auto const keyLESS = "LESS"_s;
+auto const keyLESS_EQUAL = "LESS_EQUAL"_s;
+auto const keyMATCHES = "MATCHES"_s;
+auto const keyNOT = "NOT"_s;
+auto const keyOR = "OR"_s;
+auto const keyParenL = "("_s;
+auto const keyParenR = ")"_s;
+auto const keyPOLICY = "POLICY"_s;
+auto const keySTREQUAL = "STREQUAL"_s;
+auto const keySTRGREATER = "STRGREATER"_s;
+auto const keySTRGREATER_EQUAL = "STRGREATER_EQUAL"_s;
+auto const keySTRLESS = "STRLESS"_s;
+auto const keySTRLESS_EQUAL = "STRLESS_EQUAL"_s;
+auto const keyTARGET = "TARGET"_s;
+auto const keyTEST = "TEST"_s;
+auto const keyVERSION_EQUAL = "VERSION_EQUAL"_s;
+auto const keyVERSION_GREATER = "VERSION_GREATER"_s;
+auto const keyVERSION_GREATER_EQUAL = "VERSION_GREATER_EQUAL"_s;
+auto const keyVERSION_LESS = "VERSION_LESS"_s;
+auto const keyVERSION_LESS_EQUAL = "VERSION_LESS_EQUAL"_s;
+
+cmSystemTools::CompareOp const MATCH2CMPOP[5] = {
+ cmSystemTools::OP_LESS, cmSystemTools::OP_LESS_EQUAL,
+ cmSystemTools::OP_GREATER, cmSystemTools::OP_GREATER_EQUAL,
+ cmSystemTools::OP_EQUAL
+};
+
+// Run-Time to Compile-Time template selector
+template <template <typename> class Comp, template <typename> class... Ops>
+struct cmRt2CtSelector
+{
+ template <typename T>
+ static bool eval(int r, T lhs, T rhs)
+ {
+ switch (r) {
+ case 0:
+ return false;
+ case 1:
+ return Comp<T>()(lhs, rhs);
+ default:
+ return cmRt2CtSelector<Ops...>::eval(r - 1, lhs, rhs);
+ }
+ }
+};
+
+template <template <typename> class Comp>
+struct cmRt2CtSelector<Comp>
+{
+ template <typename T>
+ static bool eval(int r, T lhs, T rhs)
+ {
+ return r == 1 && Comp<T>()(lhs, rhs);
+ }
+};
+
+std::string bool2string(bool const value)
+{
+ return std::string(std::size_t(1), static_cast<char>('0' + int(value)));
+}
+
+bool looksLikeSpecialVariable(const std::string& var,
+ cm::static_string_view prefix,
+ const std::size_t varNameLen)
+{
+ // NOTE Expecting a variable name at least 1 char length:
+ // <prefix> + `{` + <varname> + `}`
+ return ((prefix.size() + 3) <= varNameLen) &&
+ cmHasPrefix(var, cmStrCat(prefix, '{')) && var[varNameLen - 1] == '}';
+}
+} // anonymous namespace
+
+#if defined(__SUNPRO_CC)
+# define CM_INHERIT_CTOR(Class, Base, Tpl) \
+ template <typename... Args> \
+ Class(Args&&... args) \
+ : Base Tpl(std::forward<Args>(args)...) \
+ { \
+ }
+#else
+# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base
+#endif
+
+// BEGIN cmConditionEvaluator::cmArgumentList
+class cmConditionEvaluator::cmArgumentList
+ : public std::list<cmExpandedCommandArgument>
+{
+ using base_t = std::list<cmExpandedCommandArgument>;
+
+public:
+ CM_INHERIT_CTOR(cmArgumentList, list, <cmExpandedCommandArgument>);
+
+ class CurrentAndNextIter
+ {
+ friend class cmConditionEvaluator::cmArgumentList;
+
+ public:
+ base_t::iterator current;
+ base_t::iterator next;
+
+ CurrentAndNextIter advance(base_t& args)
+ {
+ this->current = std::next(this->current);
+ this->next =
+ std::next(this->current, difference_type(this->current != args.end()));
+ return *this;
+ }
+
+ private:
+ CurrentAndNextIter(base_t& args)
+ : current(args.begin())
+ , next(std::next(this->current,
+ difference_type(this->current != args.end())))
+ {
+ }
+ };
+
+ class CurrentAndTwoMoreIter
+ {
+ friend class cmConditionEvaluator::cmArgumentList;
+
+ public:
+ base_t::iterator current;
+ base_t::iterator next;
+ base_t::iterator nextnext;
+
+ CurrentAndTwoMoreIter advance(base_t& args)
+ {
+ this->current = std::next(this->current);
+ this->next =
+ std::next(this->current, difference_type(this->current != args.end()));
+ this->nextnext =
+ std::next(this->next, difference_type(this->next != args.end()));
+ return *this;
+ }
+
+ private:
+ CurrentAndTwoMoreIter(base_t& args)
+ : current(args.begin())
+ , next(std::next(this->current,
+ difference_type(this->current != args.end())))
+ , nextnext(
+ std::next(this->next, difference_type(this->next != args.end())))
+ {
+ }
+ };
+
+ CurrentAndNextIter make2ArgsIterator() { return *this; }
+ CurrentAndTwoMoreIter make3ArgsIterator() { return *this; }
+
+ template <typename Iter>
+ void ReduceOneArg(const bool value, Iter args)
+ {
+ *args.current = cmExpandedCommandArgument(bool2string(value), true);
+ this->erase(args.next);
+ }
+
+ void ReduceTwoArgs(const bool value, CurrentAndTwoMoreIter args)
+ {
+ *args.current = cmExpandedCommandArgument(bool2string(value), true);
+ this->erase(args.nextnext);
+ this->erase(args.next);
+ }
+};
+
+// END cmConditionEvaluator::cmArgumentList
cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile,
cmListFileBacktrace bt)
@@ -99,25 +248,29 @@ bool cmConditionEvaluator::IsTrue(
// now loop through the arguments and see if we can reduce any of them
// we do this multiple times. Once for each level of precedence
// parens
- if (!this->HandleLevel0(newArgs, errorString, status)) {
- return false;
- }
- // predicates
- if (!this->HandleLevel1(newArgs, errorString, status)) {
- return false;
- }
- // binary ops
- if (!this->HandleLevel2(newArgs, errorString, status)) {
- return false;
- }
+ using handlerFn_t = bool (cmConditionEvaluator::*)(
+ cmArgumentList&, std::string&, MessageType&);
+ const std::array<handlerFn_t, 5> handlers = { {
+ &cmConditionEvaluator::HandleLevel0, // parenthesis
+ &cmConditionEvaluator::HandleLevel1, // predicates
+ &cmConditionEvaluator::HandleLevel2, // binary ops
+ &cmConditionEvaluator::HandleLevel3, // NOT
+ &cmConditionEvaluator::HandleLevel4 // AND OR
+ } };
+ for (auto fn : handlers) {
+ // Call the reducer 'till there is anything to reduce...
+ // (i.e., if after an iteration the size becomes smaller)
+ auto levelResult = true;
+ for (auto beginSize = newArgs.size();
+ (levelResult = (this->*fn)(newArgs, errorString, status)) &&
+ newArgs.size() < beginSize;
+ beginSize = newArgs.size()) {
+ }
- // NOT
- if (!this->HandleLevel3(newArgs, errorString, status)) {
- return false;
- }
- // AND OR
- if (!this->HandleLevel4(newArgs, errorString, status)) {
- return false;
+ if (!levelResult) {
+ // NOTE `errorString` supposed to be set already
+ return false;
+ }
}
// now at the end there should only be one argument left
@@ -132,7 +285,7 @@ bool cmConditionEvaluator::IsTrue(
}
//=========================================================================
-cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
+cmValue cmConditionEvaluator::GetDefinitionIfUnquoted(
cmExpandedCommandArgument const& argument) const
{
if ((this->Policy54Status != cmPolicies::WARN &&
@@ -141,17 +294,19 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
return nullptr;
}
- cmProp def = this->Makefile.GetDefinition(argument.GetValue());
+ cmValue def = this->Makefile.GetDefinition(argument.GetValue());
if (def && argument.WasQuoted() &&
this->Policy54Status == cmPolicies::WARN) {
if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
std::ostringstream e;
- e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n";
- e << "Quoted variables like \"" << argument.GetValue()
- << "\" will no longer be dereferenced "
- "when the policy is set to NEW. "
+ // clang-format off
+ e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054))
+ << "\n"
+ "Quoted variables like \"" << argument.GetValue() << "\" "
+ "will no longer be dereferenced when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
+ // clang-format on
this->Makefile.GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
@@ -162,21 +317,22 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
}
//=========================================================================
-cmProp cmConditionEvaluator::GetVariableOrString(
+cmValue cmConditionEvaluator::GetVariableOrString(
const cmExpandedCommandArgument& argument) const
{
- cmProp def = this->GetDefinitionIfUnquoted(argument);
+ cmValue def = this->GetDefinitionIfUnquoted(argument);
if (!def) {
- def = &argument.GetValue();
+ def = cmValue(argument.GetValue());
}
return def;
}
//=========================================================================
-bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
- cmExpandedCommandArgument& argument) const
+bool cmConditionEvaluator::IsKeyword(
+ cm::static_string_view keyword,
+ const cmExpandedCommandArgument& argument) const
{
if ((this->Policy54Status != cmPolicies::WARN &&
this->Policy54Status != cmPolicies::OLD) &&
@@ -184,17 +340,20 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
return false;
}
- bool isKeyword = argument.GetValue() == keyword;
+ const auto isKeyword = argument.GetValue() == keyword;
if (isKeyword && argument.WasQuoted() &&
this->Policy54Status == cmPolicies::WARN) {
if (!this->Makefile.HasCMP0054AlreadyBeenReported(this->Backtrace.Top())) {
std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n";
- e << "Quoted keywords like \"" << argument.GetValue()
- << "\" will no longer be interpreted as keywords "
+ // clang-format off
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)
+ << "\n"
+ "Quoted keywords like \"" << argument.GetValue() << "\" "
+ "will no longer be interpreted as keywords "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
+ // clang-format on
this->Makefile.GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, e.str(), this->Backtrace);
@@ -208,15 +367,7 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword,
bool cmConditionEvaluator::GetBooleanValue(
cmExpandedCommandArgument& arg) const
{
- // Check basic constants.
- if (arg == "0") {
- return false;
- }
- if (arg == "1") {
- return true;
- }
-
- // Check named constants.
+ // Check basic and named constants.
if (cmIsOn(arg.GetValue())) {
return true;
}
@@ -227,7 +378,7 @@ bool cmConditionEvaluator::GetBooleanValue(
// Check for numbers.
if (!arg.empty()) {
char* end;
- double d = strtod(arg.GetValue().c_str(), &end);
+ const double d = std::strtod(arg.GetValue().c_str(), &end);
if (*end == '\0') {
// The whole string is a number. Use C conversion to bool.
return static_cast<bool>(d);
@@ -235,14 +386,14 @@ bool cmConditionEvaluator::GetBooleanValue(
}
// Check definition.
- cmProp def = this->GetDefinitionIfUnquoted(arg);
+ cmValue def = this->GetDefinitionIfUnquoted(arg);
return !cmIsOff(def);
}
//=========================================================================
// Boolean value behavior from CMake 2.6.4 and below.
bool cmConditionEvaluator::GetBooleanValueOld(
- cmExpandedCommandArgument const& arg, bool one) const
+ cmExpandedCommandArgument const& arg, bool const one) const
{
if (one) {
// Old IsTrue behavior for single argument.
@@ -252,13 +403,13 @@ bool cmConditionEvaluator::GetBooleanValueOld(
if (arg == "1") {
return true;
}
- cmProp def = this->GetDefinitionIfUnquoted(arg);
+ cmValue def = this->GetDefinitionIfUnquoted(arg);
return !cmIsOff(def);
}
// Old GetVariableOrNumber behavior.
- cmProp def = this->GetDefinitionIfUnquoted(arg);
- if (!def && atoi(arg.GetValue().c_str())) {
- def = &arg.GetValue();
+ cmValue def = this->GetDefinitionIfUnquoted(arg);
+ if (!def && std::atoi(arg.GetValue().c_str())) {
+ def = cmValue(arg.GetValue());
}
return !cmIsOff(def);
}
@@ -267,7 +418,7 @@ bool cmConditionEvaluator::GetBooleanValueOld(
// returns the resulting boolean value
bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
cmExpandedCommandArgument& newArg, std::string& errorString,
- MessageType& status, bool oneArg) const
+ MessageType& status, bool const oneArg) const
{
// Use the policy if it is set.
if (this->Policy12Status == cmPolicies::NEW) {
@@ -278,8 +429,8 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
}
// Check policy only if old and new results differ.
- bool newResult = this->GetBooleanValue(newArg);
- bool oldResult = this->GetBooleanValueOld(newArg, oneArg);
+ const auto newResult = this->GetBooleanValue(newArg);
+ const auto oldResult = this->GetBooleanValueOld(newArg, oneArg);
if (newResult != oldResult) {
switch (this->Policy12Status) {
case cmPolicies::WARN:
@@ -296,6 +447,7 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
"\" appears in a conditional statement. " +
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012);
status = MessageType::FATAL_ERROR;
+ break;
}
case cmPolicies::NEW:
break;
@@ -304,56 +456,31 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference(
return newResult;
}
-//=========================================================================
-void cmConditionEvaluator::IncrementArguments(
- cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const
+template <int N>
+inline int cmConditionEvaluator::matchKeysImpl(
+ const cmExpandedCommandArgument&)
{
- if (argP1 != newArgs.end()) {
- argP1++;
- argP2 = argP1;
- if (argP1 != newArgs.end()) {
- argP2++;
- }
- }
+ // Zero means "not found"
+ return 0;
}
-//=========================================================================
-// helper function to reduce code duplication
-void cmConditionEvaluator::HandlePredicate(
- bool value, int& reducible, cmArgumentList::iterator& arg,
- cmArgumentList& newArgs, cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const
+template <int N, typename T, typename... Keys>
+inline int cmConditionEvaluator::matchKeysImpl(
+ const cmExpandedCommandArgument& arg, T current, Keys... key)
{
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
+ if (this->IsKeyword(current, arg)) {
+ // Stop searching as soon as smth has found
+ return N;
}
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
+ return matchKeysImpl<N + 1>(arg, key...);
}
-//=========================================================================
-// helper function to reduce code duplication
-void cmConditionEvaluator::HandleBinaryOp(bool value, int& reducible,
- cmArgumentList::iterator& arg,
- cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2)
+template <typename... Keys>
+inline int cmConditionEvaluator::matchKeys(
+ const cmExpandedCommandArgument& arg, Keys... key)
{
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
+ // Get index of the matched key (1-based)
+ return matchKeysImpl<1>(arg, key...);
}
//=========================================================================
@@ -362,55 +489,35 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- while (arg != newArgs.end()) {
- if (this->IsKeyword(keyParenL, *arg)) {
- // search for the closing paren for this opening one
- cmArgumentList::iterator argClose;
- argClose = arg;
- argClose++;
- unsigned int depth = 1;
- while (argClose != newArgs.end() && depth) {
- if (this->IsKeyword(keyParenL, *argClose)) {
- depth++;
- }
- if (this->IsKeyword(keyParenR, *argClose)) {
- depth--;
- }
- argClose++;
- }
- if (depth) {
- errorString = "mismatched parenthesis in condition";
- status = MessageType::FATAL_ERROR;
- return false;
- }
- // store the reduced args in this vector
- std::vector<cmExpandedCommandArgument> newArgs2;
-
- // copy to the list structure
- auto argP1 = arg;
- argP1++;
- cm::append(newArgs2, argP1, argClose);
- newArgs2.pop_back();
- // now recursively invoke IsTrue to handle the values inside the
- // parenthetical expression
- bool value = this->IsTrue(newArgs2, errorString, status);
- if (value) {
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- argP1 = arg;
- argP1++;
- // remove the now evaluated parenthetical expression
- newArgs.erase(argP1, argClose);
+ for (auto arg = newArgs.begin(); arg != newArgs.end(); ++arg) {
+ if (this->IsKeyword(keyParenL, *arg)) {
+ // search for the closing paren for this opening one
+ auto depth = 1;
+ auto argClose = std::next(arg);
+ for (; argClose != newArgs.end() && depth; ++argClose) {
+ depth += int(this->IsKeyword(keyParenL, *argClose)) -
+ int(this->IsKeyword(keyParenR, *argClose));
}
- ++arg;
+ if (depth) {
+ errorString = "mismatched parenthesis in condition";
+ status = MessageType::FATAL_ERROR;
+ return false;
+ }
+
+ // store the reduced args in this vector
+ auto argOpen = std::next(arg);
+ const std::vector<cmExpandedCommandArgument> subExpr(
+ argOpen, std::prev(argClose));
+
+ // now recursively invoke IsTrue to handle the values inside the
+ // parenthetical expression
+ const auto value = this->IsTrue(subExpr, errorString, status);
+ *arg = cmExpandedCommandArgument(bool2string(value), true);
+ argOpen = std::next(arg);
+ // remove the now evaluated parenthetical expression
+ newArgs.erase(argOpen, argClose);
}
- } while (reducible);
+ }
return true;
}
@@ -419,96 +526,104 @@ bool cmConditionEvaluator::HandleLevel0(cmArgumentList& newArgs,
bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
MessageType&)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- // does a file exist
- if (this->IsKeyword(keyEXISTS, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileExists(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a directory with this name exist
- if (this->IsKeyword(keyIS_DIRECTORY, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(
- cmSystemTools::FileIsDirectory(argP1->GetValue()), reducible, arg,
- newArgs, argP1, argP2);
- }
- // does a symlink with this name exist
- if (this->IsKeyword(keyIS_SYMLINK, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsSymlink(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // is the given path an absolute path ?
- if (this->IsKeyword(keyIS_ABSOLUTE, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(cmSystemTools::FileIsFullPath(argP1->GetValue()),
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a command exist
- if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) {
- cmState::Command command =
- this->Makefile.GetState()->GetCommand(argP1->GetValue());
- this->HandlePredicate(command != nullptr, reducible, arg, newArgs,
- argP1, argP2);
- }
- // does a policy exist
- if (this->IsKeyword(keyPOLICY, *arg) && argP1 != newArgs.end()) {
- cmPolicies::PolicyID pid;
- this->HandlePredicate(
- cmPolicies::GetPolicyID(argP1->GetValue().c_str(), pid), reducible,
- arg, newArgs, argP1, argP2);
- }
- // does a target exist
- if (this->IsKeyword(keyTARGET, *arg) && argP1 != newArgs.end()) {
- this->HandlePredicate(
- this->Makefile.FindTargetToUse(argP1->GetValue()) != nullptr,
- reducible, arg, newArgs, argP1, argP2);
- }
- // does a test exist
- if (this->Policy64Status != cmPolicies::OLD &&
- this->Policy64Status != cmPolicies::WARN) {
- if (this->IsKeyword(keyTEST, *arg) && argP1 != newArgs.end()) {
- const cmTest* haveTest = this->Makefile.GetTest(argP1->GetValue());
- this->HandlePredicate(haveTest != nullptr, reducible, arg, newArgs,
- argP1, argP2);
- }
- } else if (this->Policy64Status == cmPolicies::WARN &&
- this->IsKeyword(keyTEST, *arg)) {
+ const auto policy64IsOld = this->Policy64Status == cmPolicies::OLD ||
+ this->Policy64Status == cmPolicies::WARN;
+
+ for (auto args = newArgs.make2ArgsIterator(); args.current != newArgs.end();
+ args.advance(newArgs)) {
+
+ auto policyCheck = [&, this](const cmPolicies::PolicyID id,
+ const cmPolicies::PolicyStatus status,
+ const cm::static_string_view kw) {
+ if (status == cmPolicies::WARN && this->IsKeyword(kw, *args.current)) {
std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n";
- e << "TEST will be interpreted as an operator "
+ e << cmPolicies::GetPolicyWarning(id) << "\n"
+ << kw
+ << " will be interpreted as an operator "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
}
- // is a variable defined
- if (this->IsKeyword(keyDEFINED, *arg) && argP1 != newArgs.end()) {
- size_t argP1len = argP1->GetValue().size();
- bool bdef = false;
- if (argP1len > 4 && cmHasLiteralPrefix(argP1->GetValue(), "ENV{") &&
- argP1->GetValue().operator[](argP1len - 1) == '}') {
- std::string env = argP1->GetValue().substr(4, argP1len - 5);
- bdef = cmSystemTools::HasEnv(env);
- } else if (argP1len > 6 &&
- cmHasLiteralPrefix(argP1->GetValue(), "CACHE{") &&
- argP1->GetValue().operator[](argP1len - 1) == '}') {
- std::string cache = argP1->GetValue().substr(6, argP1len - 7);
- bdef =
- this->Makefile.GetState()->GetCacheEntryValue(cache) != nullptr;
- } else {
- bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
- }
- this->HandlePredicate(bdef, reducible, arg, newArgs, argP1, argP2);
+ };
+
+ // NOTE Checking policies for warnings are not require an access to the
+ // next arg. Check them first!
+ policyCheck(cmPolicies::CMP0064, this->Policy64Status, keyTEST);
+
+ // NOTE Fail fast: All the predicates below require the next arg to be
+ // valid
+ if (args.next == newArgs.end()) {
+ continue;
+ }
+
+ // does a file exist
+ if (this->IsKeyword(keyEXISTS, *args.current)) {
+ newArgs.ReduceOneArg(cmSystemTools::FileExists(args.next->GetValue()),
+ args);
+ }
+ // does a directory with this name exist
+ else if (this->IsKeyword(keyIS_DIRECTORY, *args.current)) {
+ newArgs.ReduceOneArg(
+ cmSystemTools::FileIsDirectory(args.next->GetValue()), args);
+ }
+ // does a symlink with this name exist
+ else if (this->IsKeyword(keyIS_SYMLINK, *args.current)) {
+ newArgs.ReduceOneArg(cmSystemTools::FileIsSymlink(args.next->GetValue()),
+ args);
+ }
+ // is the given path an absolute path ?
+ else if (this->IsKeyword(keyIS_ABSOLUTE, *args.current)) {
+ newArgs.ReduceOneArg(
+ cmSystemTools::FileIsFullPath(args.next->GetValue()), args);
+ }
+ // does a command exist
+ else if (this->IsKeyword(keyCOMMAND, *args.current)) {
+ newArgs.ReduceOneArg(
+ bool(this->Makefile.GetState()->GetCommand(args.next->GetValue())),
+ args);
+ }
+ // does a policy exist
+ else if (this->IsKeyword(keyPOLICY, *args.current)) {
+ cmPolicies::PolicyID pid;
+ newArgs.ReduceOneArg(
+ cmPolicies::GetPolicyID(args.next->GetValue().c_str(), pid), args);
+ }
+ // does a target exist
+ else if (this->IsKeyword(keyTARGET, *args.current)) {
+ newArgs.ReduceOneArg(
+ bool(this->Makefile.FindTargetToUse(args.next->GetValue())), args);
+ }
+ // is a variable defined
+ else if (this->IsKeyword(keyDEFINED, *args.current)) {
+ const auto& var = args.next->GetValue();
+ const auto varNameLen = var.size();
+
+ auto result = false;
+ if (looksLikeSpecialVariable(var, "ENV"_s, varNameLen)) {
+ const auto env = args.next->GetValue().substr(4, varNameLen - 5);
+ result = cmSystemTools::HasEnv(env);
+ }
+
+ else if (looksLikeSpecialVariable(var, "CACHE"_s, varNameLen)) {
+ const auto cache = args.next->GetValue().substr(6, varNameLen - 7);
+ result = bool(this->Makefile.GetState()->GetCacheEntryValue(cache));
}
- ++arg;
+
+ else {
+ result = this->Makefile.IsDefinitionSet(args.next->GetValue());
+ }
+ newArgs.ReduceOneArg(result, args);
+ }
+ // does a test exist
+ else if (this->IsKeyword(keyTEST, *args.current)) {
+ if (policy64IsOld) {
+ continue;
+ }
+ newArgs.ReduceOneArg(bool(this->Makefile.GetTest(args.next->GetValue())),
+ args);
}
- } while (reducible);
+ }
return true;
}
@@ -518,178 +633,142 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- std::string def_buf;
- cmProp def;
- cmProp def2;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyMATCHES, *argP1)) {
- def = this->GetDefinitionIfUnquoted(*arg);
- if (!def) {
- def = &arg->GetValue();
- } else if (cmHasLiteralPrefix(arg->GetValue(), "CMAKE_MATCH_")) {
- // The string to match is owned by our match result variables.
- // Move it to our own buffer before clearing them.
- def_buf = *def;
- def = &def_buf;
- }
- const std::string& rex = argP2->GetValue();
- this->Makefile.ClearMatches();
- cmsys::RegularExpression regEntry;
- if (!regEntry.compile(rex)) {
- std::ostringstream error;
- error << "Regular expression \"" << rex << "\" cannot compile";
- errorString = error.str();
- status = MessageType::FATAL_ERROR;
- return false;
- }
- if (regEntry.find(*def)) {
- this->Makefile.StoreMatches(regEntry);
- *arg = cmExpandedCommandArgument("1", true);
- } else {
- *arg = cmExpandedCommandArgument("0", true);
- }
- newArgs.erase(argP2);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
- }
+ for (auto args = newArgs.make3ArgsIterator(); args.current != newArgs.end();
+ args.advance(newArgs)) {
- if (argP1 != newArgs.end() && this->IsKeyword(keyMATCHES, *arg)) {
- *arg = cmExpandedCommandArgument("0", true);
- newArgs.erase(argP1);
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- reducible = 1;
- }
+ int matchNo;
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keyLESS, *argP1) ||
- this->IsKeyword(keyLESS_EQUAL, *argP1) ||
- this->IsKeyword(keyGREATER, *argP1) ||
- this->IsKeyword(keyGREATER_EQUAL, *argP1) ||
- this->IsKeyword(keyEQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- double lhs;
- double rhs;
- bool result;
- if (sscanf(def->c_str(), "%lg", &lhs) != 1 ||
- sscanf(def2->c_str(), "%lg", &rhs) != 1) {
- result = false;
- } else if (*(argP1) == keyLESS) {
- result = (lhs < rhs);
- } else if (*(argP1) == keyLESS_EQUAL) {
- result = (lhs <= rhs);
- } else if (*(argP1) == keyGREATER) {
- result = (lhs > rhs);
- } else if (*(argP1) == keyGREATER_EQUAL) {
- result = (lhs >= rhs);
- } else {
- result = (lhs == rhs);
- }
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
- }
+ // NOTE Handle special case `if(... BLAH_BLAH MATCHES)`
+ // (i.e., w/o regex to match which is possibly result of
+ // variable expansion to an empty string)
+ if (args.next != newArgs.end() &&
+ this->IsKeyword(keyMATCHES, *args.current)) {
+ newArgs.ReduceOneArg(false, args);
+ }
+
+ // NOTE Fail fast: All the binary ops below require 2 arguments.
+ else if (args.next == newArgs.end() || args.nextnext == newArgs.end()) {
+ continue;
+ }
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keySTRLESS, *argP1) ||
- this->IsKeyword(keySTRLESS_EQUAL, *argP1) ||
- this->IsKeyword(keySTRGREATER, *argP1) ||
- this->IsKeyword(keySTRGREATER_EQUAL, *argP1) ||
- this->IsKeyword(keySTREQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- int val = (*def).compare(*def2);
- bool result;
- if (*(argP1) == keySTRLESS) {
- result = (val < 0);
- } else if (*(argP1) == keySTRLESS_EQUAL) {
- result = (val <= 0);
- } else if (*(argP1) == keySTRGREATER) {
- result = (val > 0);
- } else if (*(argP1) == keySTRGREATER_EQUAL) {
- result = (val >= 0);
- } else // strequal
- {
- result = (val == 0);
- }
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ else if (this->IsKeyword(keyMATCHES, *args.next)) {
+ cmValue def = this->GetDefinitionIfUnquoted(*args.current);
+
+ std::string def_buf;
+ if (!def) {
+ def = cmValue(args.current->GetValue());
+ } else if (cmHasLiteralPrefix(args.current->GetValue(),
+ "CMAKE_MATCH_")) {
+ // The string to match is owned by our match result variables.
+ // Move it to our own buffer before clearing them.
+ def_buf = *def;
+ def = cmValue(def_buf);
}
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- (this->IsKeyword(keyVERSION_LESS, *argP1) ||
- this->IsKeyword(keyVERSION_LESS_EQUAL, *argP1) ||
- this->IsKeyword(keyVERSION_GREATER, *argP1) ||
- this->IsKeyword(keyVERSION_GREATER_EQUAL, *argP1) ||
- this->IsKeyword(keyVERSION_EQUAL, *argP1))) {
- def = this->GetVariableOrString(*arg);
- def2 = this->GetVariableOrString(*argP2);
- cmSystemTools::CompareOp op;
- if (*argP1 == keyVERSION_LESS) {
- op = cmSystemTools::OP_LESS;
- } else if (*argP1 == keyVERSION_LESS_EQUAL) {
- op = cmSystemTools::OP_LESS_EQUAL;
- } else if (*argP1 == keyVERSION_GREATER) {
- op = cmSystemTools::OP_GREATER;
- } else if (*argP1 == keyVERSION_GREATER_EQUAL) {
- op = cmSystemTools::OP_GREATER_EQUAL;
- } else { // version_equal
- op = cmSystemTools::OP_EQUAL;
- }
- bool result =
- cmSystemTools::VersionCompare(op, def->c_str(), def2->c_str());
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
+ this->Makefile.ClearMatches();
+
+ const auto& rex = args.nextnext->GetValue();
+ cmsys::RegularExpression regEntry;
+ if (!regEntry.compile(rex)) {
+ std::ostringstream error;
+ error << "Regular expression \"" << rex << "\" cannot compile";
+ errorString = error.str();
+ status = MessageType::FATAL_ERROR;
+ return false;
}
- // is file A newer than file B
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyIS_NEWER_THAN, *argP1)) {
- int fileIsNewer = 0;
- cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
- arg->GetValue(), (argP2)->GetValue(), &fileIsNewer);
- this->HandleBinaryOp(
- (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), reducible, arg,
- newArgs, argP1, argP2);
+ const auto match = regEntry.find(*def);
+ if (match) {
+ this->Makefile.StoreMatches(regEntry);
}
+ newArgs.ReduceTwoArgs(match, args);
+ }
+
+ else if ((matchNo =
+ this->matchKeys(*args.next, keyLESS, keyLESS_EQUAL, keyGREATER,
+ keyGREATER_EQUAL, keyEQUAL))) {
+
+ cmValue ldef = this->GetVariableOrString(*args.current);
+ cmValue rdef = this->GetVariableOrString(*args.nextnext);
+
+ double lhs;
+ double rhs;
+ auto parseDoubles = [&]() {
+ return std::sscanf(ldef->c_str(), "%lg", &lhs) == 1 &&
+ std::sscanf(rdef->c_str(), "%lg", &rhs) == 1;
+ };
+ // clang-format off
+ const auto result = parseDoubles() &&
+ cmRt2CtSelector<
+ std::less, std::less_equal,
+ std::greater, std::greater_equal,
+ std::equal_to
+ >::eval(matchNo, lhs, rhs);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ else if ((matchNo = this->matchKeys(*args.next, keySTRLESS,
+ keySTRLESS_EQUAL, keySTRGREATER,
+ keySTRGREATER_EQUAL, keySTREQUAL))) {
+
+ const cmValue lhs = this->GetVariableOrString(*args.current);
+ const cmValue rhs = this->GetVariableOrString(*args.nextnext);
+ const auto val = (*lhs).compare(*rhs);
+ // clang-format off
+ const auto result = cmRt2CtSelector<
+ std::less, std::less_equal,
+ std::greater, std::greater_equal,
+ std::equal_to
+ >::eval(matchNo, val, 0);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ else if ((matchNo =
+ this->matchKeys(*args.next, keyVERSION_LESS,
+ keyVERSION_LESS_EQUAL, keyVERSION_GREATER,
+ keyVERSION_GREATER_EQUAL, keyVERSION_EQUAL))) {
+ const auto op = MATCH2CMPOP[matchNo - 1];
+ const std::string& lhs = this->GetVariableOrString(*args.current);
+ const std::string& rhs = this->GetVariableOrString(*args.nextnext);
+ const auto result = cmSystemTools::VersionCompare(op, lhs, rhs);
+ newArgs.ReduceTwoArgs(result, args);
+ }
+
+ // is file A newer than file B
+ else if (this->IsKeyword(keyIS_NEWER_THAN, *args.next)) {
+ auto fileIsNewer = 0;
+ cmsys::Status ftcStatus = cmSystemTools::FileTimeCompare(
+ args.current->GetValue(), args.nextnext->GetValue(), &fileIsNewer);
+ newArgs.ReduceTwoArgs(
+ (!ftcStatus || fileIsNewer == 1 || fileIsNewer == 0), args);
+ }
+
+ else if (this->IsKeyword(keyIN_LIST, *args.next)) {
- if (argP1 != newArgs.end() && argP2 != newArgs.end() &&
- this->IsKeyword(keyIN_LIST, *argP1)) {
- if (this->Policy57Status != cmPolicies::OLD &&
- this->Policy57Status != cmPolicies::WARN) {
- bool result = false;
-
- def = this->GetVariableOrString(*arg);
- def2 = this->Makefile.GetDefinition(argP2->GetValue());
-
- if (def2) {
- std::vector<std::string> list = cmExpandedList(*def2, true);
- result = cm::contains(list, *def);
- }
-
- this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2);
- } else if (this->Policy57Status == cmPolicies::WARN) {
- std::ostringstream e;
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n";
- e << "IN_LIST will be interpreted as an operator "
- "when the policy is set to NEW. "
- "Since the policy is not set the OLD behavior will be used.";
-
- this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
- }
+ if (this->Policy57Status != cmPolicies::OLD &&
+ this->Policy57Status != cmPolicies::WARN) {
+
+ cmValue lhs = this->GetVariableOrString(*args.current);
+ cmValue rhs = this->Makefile.GetDefinition(args.nextnext->GetValue());
+
+ newArgs.ReduceTwoArgs(
+ rhs && cm::contains(cmExpandedList(*rhs, true), *lhs), args);
}
- ++arg;
+ else if (this->Policy57Status == cmPolicies::WARN) {
+ std::ostringstream e;
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057)
+ << "\n"
+ "IN_LIST will be interpreted as an operator "
+ "when the policy is set to NEW. "
+ "Since the policy is not set the OLD behavior will be used.";
+
+ this->Makefile.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ }
}
- } while (reducible);
+ }
return true;
}
@@ -699,23 +778,14 @@ bool cmConditionEvaluator::HandleLevel3(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && this->IsKeyword(keyNOT, *arg)) {
- bool rhs = this->GetBooleanValueWithAutoDereference(
- *argP1, errorString, status);
- this->HandlePredicate(!rhs, reducible, arg, newArgs, argP1, argP2);
- }
- ++arg;
+ for (auto args = newArgs.make2ArgsIterator(); args.next != newArgs.end();
+ args.advance(newArgs)) {
+ if (this->IsKeyword(keyNOT, *args.current)) {
+ const auto rhs = this->GetBooleanValueWithAutoDereference(
+ *args.next, errorString, status);
+ newArgs.ReduceOneArg(!rhs, args);
}
- } while (reducible);
+ }
return true;
}
@@ -725,38 +795,24 @@ bool cmConditionEvaluator::HandleLevel4(cmArgumentList& newArgs,
std::string& errorString,
MessageType& status)
{
- int reducible;
- bool lhs;
- bool rhs;
- do {
- reducible = 0;
- auto arg = newArgs.begin();
- cmArgumentList::iterator argP1;
- cmArgumentList::iterator argP2;
- while (arg != newArgs.end()) {
- argP1 = arg;
- this->IncrementArguments(newArgs, argP1, argP2);
- if (argP1 != newArgs.end() && this->IsKeyword(keyAND, *argP1) &&
- argP2 != newArgs.end()) {
- lhs =
- this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
- rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
- status);
- this->HandleBinaryOp((lhs && rhs), reducible, arg, newArgs, argP1,
- argP2);
- }
-
- if (argP1 != newArgs.end() && this->IsKeyword(keyOR, *argP1) &&
- argP2 != newArgs.end()) {
- lhs =
- this->GetBooleanValueWithAutoDereference(*arg, errorString, status);
- rhs = this->GetBooleanValueWithAutoDereference(*argP2, errorString,
- status);
- this->HandleBinaryOp((lhs || rhs), reducible, arg, newArgs, argP1,
- argP2);
- }
- ++arg;
+ for (auto args = newArgs.make3ArgsIterator(); args.nextnext != newArgs.end();
+ args.advance(newArgs)) {
+
+ int matchNo;
+
+ if ((matchNo = this->matchKeys(*args.next, keyAND, keyOR))) {
+ const auto lhs = this->GetBooleanValueWithAutoDereference(
+ *args.current, errorString, status);
+ const auto rhs = this->GetBooleanValueWithAutoDereference(
+ *args.nextnext, errorString, status);
+ // clang-format off
+ const auto result =
+ cmRt2CtSelector<
+ std::logical_and, std::logical_or
+ >::eval(matchNo, lhs, rhs);
+ // clang-format on
+ newArgs.ReduceTwoArgs(result, args);
}
- } while (reducible);
+ }
return true;
}
diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h
index cf00ede35..37b7825b3 100644
--- a/Source/cmConditionEvaluator.h
+++ b/Source/cmConditionEvaluator.h
@@ -4,23 +4,22 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <list>
#include <string>
#include <vector>
-#include "cmExpandedCommandArgument.h"
+#include <cmext/string_view>
+
#include "cmListFileCache.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
+#include "cmValue.h"
+class cmExpandedCommandArgument;
class cmMakefile;
class cmConditionEvaluator
{
public:
- using cmArgumentList = std::list<cmExpandedCommandArgument>;
-
cmConditionEvaluator(cmMakefile& makefile, cmListFileBacktrace bt);
// this is a shared function for both If and Else to determine if the
@@ -30,14 +29,16 @@ public:
std::string& errorString, MessageType& status);
private:
+ class cmArgumentList;
+
// Filter the given variable definition based on policy CMP0054.
- cmProp GetDefinitionIfUnquoted(
+ cmValue GetDefinitionIfUnquoted(
const cmExpandedCommandArgument& argument) const;
- cmProp GetVariableOrString(const cmExpandedCommandArgument& argument) const;
+ cmValue GetVariableOrString(const cmExpandedCommandArgument& argument) const;
- bool IsKeyword(std::string const& keyword,
- cmExpandedCommandArgument& argument) const;
+ bool IsKeyword(cm::static_string_view keyword,
+ const cmExpandedCommandArgument& argument) const;
bool GetBooleanValue(cmExpandedCommandArgument& arg) const;
@@ -49,19 +50,14 @@ private:
MessageType& status,
bool oneArg = false) const;
- void IncrementArguments(cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const;
+ template <int N>
+ int matchKeysImpl(const cmExpandedCommandArgument&);
- void HandlePredicate(bool value, int& reducible,
- cmArgumentList::iterator& arg, cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2) const;
+ template <int N, typename T, typename... Keys>
+ int matchKeysImpl(const cmExpandedCommandArgument&, T, Keys...);
- void HandleBinaryOp(bool value, int& reducible,
- cmArgumentList::iterator& arg, cmArgumentList& newArgs,
- cmArgumentList::iterator& argP1,
- cmArgumentList::iterator& argP2);
+ template <typename... Keys>
+ int matchKeys(const cmExpandedCommandArgument&, Keys...);
bool HandleLevel0(cmArgumentList& newArgs, std::string& errorString,
MessageType& status);
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index aeca6b42a..6a419f681 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -16,7 +16,6 @@
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
-#cmakedefine CMake_USE_ELF_PARSER
#cmakedefine CMake_USE_MACH_PARSER
#cmakedefine CMake_USE_XCOFF_PARSER
#define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index bf181433b..971c86e59 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -19,11 +19,11 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -246,7 +246,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->SrcFileSignature = true;
cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE;
- cmProp tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
+ cmValue tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE");
if (!isTryRun && cmNonempty(tt)) {
if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) {
targetType = cmStateEnums::EXECUTABLE;
@@ -540,7 +540,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
return -1;
}
- cmProp def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
+ cmValue def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n",
cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(),
cmVersion::GetPatchVersion(), cmVersion::GetTweakVersion());
@@ -549,7 +549,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
/* Set MSVC runtime library policy to match our selection. */
- if (cmProp msvcRuntimeLibraryDefault =
+ if (cmValue msvcRuntimeLibraryDefault =
this->Makefile->GetDefinition(kCMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)) {
fprintf(fout, "cmake_policy(SET CMP0091 %s)\n",
!msvcRuntimeLibraryDefault->empty() ? "NEW" : "OLD");
@@ -564,7 +564,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
/* Set ARMClang cpu/arch policy to match outer project. */
- if (cmProp cmp0123 =
+ if (cmValue cmp0123 =
this->Makefile->GetDefinition(kCMAKE_ARMClang_CMP0123)) {
fprintf(fout, "cmake_policy(SET CMP0123 %s)\n",
*cmp0123 == "NEW"_s ? "NEW" : "OLD");
@@ -582,11 +582,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
projectLangs += " " + li;
std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE";
std::string rulesOverrideLang = cmStrCat(rulesOverrideBase, "_", li);
- if (cmProp rulesOverridePath =
+ if (cmValue rulesOverridePath =
this->Makefile->GetDefinition(rulesOverrideLang)) {
fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(),
rulesOverridePath->c_str());
- } else if (cmProp rulesOverridePath2 =
+ } else if (cmValue rulesOverridePath2 =
this->Makefile->GetDefinition(rulesOverrideBase)) {
fprintf(fout, "set(%s \"%s\")\n", rulesOverrideBase.c_str(),
rulesOverridePath2->c_str());
@@ -604,9 +604,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
for (std::string const& li : testLangs) {
std::string langFlags = "CMAKE_" + li + "_FLAGS";
- cmProp flags = this->Makefile->GetDefinition(langFlags);
+ cmValue flags = this->Makefile->GetDefinition(langFlags);
fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li.c_str(),
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(flags)).c_str());
+ cmOutputConverter::EscapeForCMake(*flags).c_str());
fprintf(fout,
"set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
" ${COMPILE_DEFINITIONS}\")\n",
@@ -626,6 +626,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
/* clang-format on */
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to do nothing.
break;
@@ -643,10 +644,9 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
for (std::string const& li : testLangs) {
std::string const langFlagsCfg =
cmStrCat("CMAKE_", li, "_FLAGS_", cfg);
- cmProp flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
- fprintf(
- fout, "set(%s %s)\n", langFlagsCfg.c_str(),
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(flagsCfg)).c_str());
+ cmValue flagsCfg = this->Makefile->GetDefinition(langFlagsCfg);
+ fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
+ cmOutputConverter::EscapeForCMake(*flagsCfg).c_str());
}
} break;
}
@@ -664,6 +664,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
/* clang-format on */
this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
}
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to do nothing.
break;
@@ -676,11 +677,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
case cmPolicies::NEW:
// NEW behavior is to pass linker flags.
{
- cmProp exeLinkFlags =
+ cmValue exeLinkFlags =
this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
- cmOutputConverter::EscapeForCMake(cmToCStrSafe(exeLinkFlags))
- .c_str());
+ cmOutputConverter::EscapeForCMake(*exeLinkFlags).c_str());
}
break;
}
@@ -762,7 +762,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
vars.insert(kCMAKE_WARN_DEPRECATED);
vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s);
- if (cmProp varListStr = this->Makefile->GetDefinition(
+ if (cmValue varListStr = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) {
std::vector<std::string> varList = cmExpandedList(*varListStr);
vars.insert(varList.begin(), varList.end());
@@ -801,7 +801,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmLocalGenerator doesn't allow building for "the other"
architecture only via CMAKE_OSX_ARCHITECTURES.
*/
- if (cmProp tcArchs = this->Makefile->GetDefinition(
+ if (cmValue tcArchs = this->Makefile->GetDefinition(
kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) {
vars.erase(kCMAKE_OSX_ARCHITECTURES);
std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs;
@@ -809,7 +809,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
for (std::string const& var : vars) {
- if (cmProp val = this->Makefile->GetDefinition(var)) {
+ if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + *val;
cmakeFlags.push_back(std::move(flag));
}
@@ -880,6 +880,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0067));
+ break;
case cmPolicies::NEW:
// NEW behavior is to honor the language standard variables.
// We already initialized honorStandard to true.
@@ -954,7 +955,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (this->Makefile->GetState()->UseGhsMultiIDE()) {
// Forward the GHS variables to the inner project cache.
for (std::string const& var : ghs_platform_vars) {
- if (cmProp val = this->Makefile->GetDefinition(var)) {
+ if (cmValue val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + "'" + *val + "'";
cmakeFlags.push_back(std::move(flag));
}
@@ -1096,7 +1097,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
std::vector<std::string> searchDirs;
searchDirs.emplace_back();
- cmProp config =
+ cmValue config =
this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
// if a config was specified try that first
if (cmNonempty(config)) {
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 233790e54..28ee24dfe 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -5,9 +5,17 @@
#if !defined(CMAKE_USE_SYSTEM_CURL) && !defined(_WIN32) && \
!defined(__APPLE__) && !defined(CURL_CA_BUNDLE) && !defined(CURL_CA_PATH)
# define CMAKE_FIND_CAFILE
-# include "cmSystemTools.h"
#endif
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+#if defined(_WIN32)
+# include <vector>
+
+# include <windows.h>
+
+# include "cmsys/Encoding.hxx"
+#endif
// curl versions before 7.21.5 did not provide this error code
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505
@@ -23,11 +31,11 @@
} \
} while (false)
-std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile)
+std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile)
{
std::string e;
- if (cafile && *cafile) {
- ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile);
+ if (!cafile.empty()) {
+ ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile.c_str());
check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
#ifdef CMAKE_FIND_CAFILE
@@ -95,3 +103,35 @@ std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
}
return e;
}
+
+std::string cmCurlFixFileURL(std::string url)
+{
+ if (!cmHasLiteralPrefix(url, "file://")) {
+ return url;
+ }
+
+ // libcurl 7.77 and below accidentally allowed spaces in URLs in some cases.
+ // One such case was file:// URLs, which CMake has long accepted as a result.
+ // Explicitly encode spaces for a URL.
+ cmSystemTools::ReplaceString(url, " ", "%20");
+
+#if defined(_WIN32)
+ // libcurl doesn't support file:// urls for unicode filenames on Windows.
+ // Convert string from UTF-8 to ACP if this is a file:// URL.
+ std::wstring wurl = cmsys::Encoding::ToWide(url);
+ if (!wurl.empty()) {
+ int mblen =
+ WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, NULL, 0, NULL, NULL);
+ if (mblen > 0) {
+ std::vector<char> chars(mblen);
+ mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, &chars[0],
+ mblen, NULL, NULL);
+ if (mblen > 0) {
+ url = &chars[0];
+ }
+ }
+ }
+#endif
+
+ return url;
+}
diff --git a/Source/cmCurl.h b/Source/cmCurl.h
index fb716f80c..b5134f466 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -8,6 +8,7 @@
#include <cm3p/curl/curl.h>
-std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr);
+std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile = {});
std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
const std::string& netrc_file);
+std::string cmCurlFixFileURL(std::string url);
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 5a2683bb8..fd0a63c29 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -19,11 +19,11 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTransformDepfile.h"
+#include "cmValue.h"
namespace {
std::string EvaluateSplitConfigGenex(
@@ -91,7 +91,7 @@ std::string EvaluateSplitConfigGenex(
// Record targets referenced by the genex.
if (utils) {
- // FIXME: What is the proper condition for a cross-dependency?
+ // Use a cross-dependency if we referenced the command config.
bool const cross = !useOutputConfig;
for (cmGeneratorTarget* gt : cge->GetTargets()) {
utils->emplace(BT<std::pair<std::string, bool>>(
@@ -176,6 +176,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse(
this->Target) };
+ bool const distinctConfigs = this->OutputConfig != this->CommandConfig;
+
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
for (cmCustomCommandLine const& cmdline : cmdlines) {
cmCustomCommandLine argv;
@@ -191,8 +193,10 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
argv.push_back(std::move(parsed_arg));
}
- // For remaining arguments, we default to the OUTPUT_CONFIG.
- useOutputConfig = true;
+ if (distinctConfigs) {
+ // For remaining arguments, we default to the OUTPUT_CONFIG.
+ useOutputConfig = true;
+ }
}
if (!argv.empty()) {
@@ -200,7 +204,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
// collect the target to add a target-level dependency on it.
cmGeneratorTarget* gt = this->LG->FindGeneratorTargetToUse(argv.front());
if (gt && gt->GetType() == cmStateEnums::EXECUTABLE) {
- // FIXME: What is the proper condition for a cross-dependency?
+ // GetArgv0Location uses the command config, so use a cross-dependency.
bool const cross = true;
this->Utilities.emplace(BT<std::pair<std::string, bool>>(
{ gt->GetName(), cross }, cc.GetBacktrace()));
@@ -284,7 +288,7 @@ void cmCustomCommandGenerator::FillEmulatorsWithArguments()
if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
!target->IsImported()) {
- cmProp emulator_property =
+ cmValue emulator_property =
target->GetProperty("CROSSCOMPILING_EMULATOR");
if (!emulator_property) {
continue;
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 4a4f87d8b..a5f8aabec 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -34,11 +34,11 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key,
return begin->Map.emplace(key, def).first->second;
}
-const std::string* cmDefinitions::Get(const std::string& key, StackIter begin,
- StackIter end)
+cmValue cmDefinitions::Get(const std::string& key, StackIter begin,
+ StackIter end)
{
Def const& def = cmDefinitions::GetInternal(key, begin, end, false);
- return def.Value ? def.Value.str_if_stable() : nullptr;
+ return def.Value ? cmValue(def.Value.str_if_stable()) : nullptr;
}
void cmDefinitions::Raise(const std::string& key, StackIter begin,
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index b650aa860..22fef807a 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -13,6 +13,7 @@
#include "cmLinkedTree.h"
#include "cmString.hxx"
+#include "cmValue.h"
/** \class cmDefinitions
* \brief Store a scope of variable definitions for CMake language.
@@ -28,8 +29,7 @@ class cmDefinitions
public:
// -- Static member functions
- static const std::string* Get(const std::string& key, StackIter begin,
- StackIter end);
+ static cmValue Get(const std::string& key, StackIter begin, StackIter end);
static void Raise(const std::string& key, StackIter begin, StackIter end);
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 46c7e3e77..eca1abdaa 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -11,9 +11,9 @@
#include "cmGeneratedFileStream.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmDepends::cmDepends(cmLocalUnixMakefileGenerator3* lg, std::string targetDir)
: LocalGenerator(lg)
@@ -232,7 +232,7 @@ void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
std::string includePathVar =
cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH");
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- cmProp includePath = mf->GetDefinition(includePathVar);
+ cmValue includePath = mf->GetDefinition(includePathVar);
if (includePath) {
cmExpandList(*includePath, this->IncludePath);
} else {
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index da37d4531..25278090a 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -10,9 +10,9 @@
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#define INCLUDE_REGEX_LINE \
"^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])"
@@ -40,12 +40,12 @@ cmDependsC::cmDependsC(cmLocalUnixMakefileGenerator3* lg,
std::string complainRegex = "^$";
{
std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN");
- if (cmProp sr = mf->GetDefinition(scanRegexVar)) {
+ if (cmValue sr = mf->GetDefinition(scanRegexVar)) {
scanRegex = *sr;
}
std::string complainRegexVar =
cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN");
- if (cmProp cr = mf->GetDefinition(complainRegexVar)) {
+ if (cmValue cr = mf->GetDefinition(complainRegexVar)) {
complainRegex = *cr;
}
}
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index a64dc27a9..d5e54ae37 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -16,9 +16,9 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// TODO: Test compiler for the case of the mod file. Some always
// use lower case and some always use upper case. I do not know if any
@@ -163,12 +163,17 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
}
+ bool building_intrinsics =
+ !mf->GetSafeDefinition("CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES")
+ .empty();
+
// Actually write dependencies to the streams.
using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
ObjectInfoMap const& objInfo = this->Internal->ObjectInfo;
for (auto const& i : objInfo) {
if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir,
- makeDepends, internalDepends)) {
+ makeDepends, internalDepends,
+ building_intrinsics)) {
return false;
}
}
@@ -307,7 +312,8 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
- std::ostream& internalDepends)
+ std::ostream& internalDepends,
+ bool buildingIntrinsics)
{
// Get the source file for this object.
std::string const& src = info.Source;
@@ -339,8 +345,13 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
makeDepends << '\n';
}
+ std::set<std::string> req = info.Requires;
+ if (buildingIntrinsics) {
+ req.insert(info.Intrinsics.begin(), info.Intrinsics.end());
+ }
+
// Write module requirements to the output stream.
- for (std::string const& i : info.Requires) {
+ for (std::string const& i : req) {
// Require only modules not provided in the same source.
if (info.Provides.find(i) != info.Provides.cend()) {
continue;
@@ -405,7 +416,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile
<< ' ' << stampFileForShell;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- cmProp cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID");
+ cmValue cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID");
if (cmNonempty(cid)) {
makeDepends << ' ' << *cid;
}
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 0d407bc3b..a74db91f3 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -72,7 +72,8 @@ protected:
std::string const& mod_dir,
std::string const& stamp_dir,
std::ostream& makeDepends,
- std::ostream& internalDepends);
+ std::ostream& internalDepends,
+ bool buildingIntrinsics);
// The source file from which to start scanning.
std::string SourceFile;
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 9a474e32c..1678ce8c6 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -17,41 +17,9 @@
#include "cmsys/FStream.hxx"
-// Include the ELF format information system header.
-#if defined(__OpenBSD__)
-# include <elf_abi.h>
-#elif defined(__HAIKU__)
-# include <elf32.h>
-# include <elf64.h>
-using Elf32_Ehdr = struct Elf32_Ehdr;
-using Elf32_Shdr = struct Elf32_Shdr;
-using Elf32_Sym = struct Elf32_Sym;
-using Elf32_Rel = struct Elf32_Rel;
-using Elf32_Rela = struct Elf32_Rela;
-# define ELFMAG0 0x7F
-# define ELFMAG1 'E'
-# define ELFMAG2 'L'
-# define ELFMAG3 'F'
-# define ET_NONE 0
-# define ET_REL 1
-# define ET_EXEC 2
-# define ET_DYN 3
-# define ET_CORE 4
-# define EM_386 3
-# define EM_SPARC 2
-# define EM_PPC 20
-#else
-# include <elf.h>
-#endif
-#if defined(__sun)
-# include <sys/link.h> // For dynamic section information
-#endif
-#ifdef _SCO_DS
-# include <link.h> // For DT_SONAME etc.
-#endif
-#ifndef DT_RUNPATH
-# define DT_RUNPATH 29
-#endif
+#include "cmelf/elf32.h"
+#include "cmelf/elf64.h"
+#include "cmelf/elf_common.h"
// Low-level byte swapping implementation.
template <size_t s>
@@ -145,6 +113,7 @@ public:
virtual std::vector<char> EncodeDynamicEntries(
const cmELF::DynamicEntryList&) = 0;
virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0;
+ virtual bool IsMips() const = 0;
virtual void PrintInfo(std::ostream& os) const = 0;
// Lookup the SONAME in the DYNAMIC section.
@@ -218,7 +187,6 @@ struct cmELFTypes32
};
// Configure the implementation template for 64-bit ELF files.
-#ifndef _SCO_DS
struct cmELFTypes64
{
using ELF_Ehdr = Elf64_Ehdr;
@@ -228,7 +196,6 @@ struct cmELFTypes64
using tagtype = ::uint64_t;
static const char* GetName() { return "64-bit"; }
};
-#endif
// Parser implementation template.
template <class Types>
@@ -262,6 +229,8 @@ public:
// Lookup a string from the dynamic section with the given tag.
StringEntry const* GetDynamicSectionString(unsigned int tag) override;
+ bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; }
+
// Print information about the ELF file.
void PrintInfo(std::ostream& os) const override
{
@@ -345,16 +314,12 @@ private:
eti == ET_CORE) {
return true;
}
-#if defined(ET_LOOS) && defined(ET_HIOS)
if (eti >= ET_LOOS && eti <= ET_HIOS) {
return true;
}
-#endif
-#if defined(ET_LOPROC) && defined(ET_HIPROC)
if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
return true;
}
-#endif
return false;
}
@@ -465,18 +430,14 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external,
break;
default: {
unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type);
-#if defined(ET_LOOS) && defined(ET_HIOS)
if (eti >= ET_LOOS && eti <= ET_HIOS) {
this->ELFType = cmELF::FileTypeSpecificOS;
break;
}
-#endif
-#if defined(ET_LOPROC) && defined(ET_HIPROC)
if (eti >= ET_LOPROC && eti <= ET_HIPROC) {
this->ELFType = cmELF::FileTypeSpecificProc;
break;
}
-#endif
std::ostringstream e;
e << "Unknown ELF file type " << eti;
this->SetErrorMessage(e.str().c_str());
@@ -681,17 +642,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
const long cmELF::TagRPath = DT_RPATH;
const long cmELF::TagRunPath = DT_RUNPATH;
-
-#ifdef DT_MIPS_RLD_MAP_REL
const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
-#else
-const long cmELF::TagMipsRldMapRel = 0;
-#endif
cmELF::cmELF(const char* fname)
{
// Try to open the file.
- auto fin = cm::make_unique<cmsys::ifstream>(fname);
+ auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary);
// Quit now if the file could not be opened.
if (!fin || !*fin) {
@@ -736,15 +692,11 @@ cmELF::cmELF(const char* fname)
// 32-bit ELF
this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>(
this, std::move(fin), order);
- }
-#ifndef _SCO_DS
- else if (ident[EI_CLASS] == ELFCLASS64) {
+ } else if (ident[EI_CLASS] == ELFCLASS64) {
// 64-bit ELF
this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>(
this, std::move(fin), order);
- }
-#endif
- else {
+ } else {
this->ErrorMessage = "ELF file class is not 32-bit or 64-bit.";
return;
}
@@ -846,6 +798,14 @@ cmELF::StringEntry const* cmELF::GetRunPath()
return nullptr;
}
+bool cmELF::IsMIPS() const
+{
+ if (this->Valid()) {
+ return this->Internal->IsMips();
+ }
+ return false;
+}
+
void cmELF::PrintInfo(std::ostream& os) const
{
if (this->Valid()) {
diff --git a/Source/cmELF.h b/Source/cmELF.h
index f88ebe992..ce8bd7fb9 100644
--- a/Source/cmELF.h
+++ b/Source/cmELF.h
@@ -11,10 +11,6 @@
#include <utility>
#include <vector>
-#if !defined(CMake_USE_ELF_PARSER)
-# error "This file may be included only if CMake_USE_ELF_PARSER is enabled."
-#endif
-
class cmELFInternal;
/** \class cmELF
@@ -102,6 +98,9 @@ public:
/** Get the RUNPATH field if any. */
StringEntry const* GetRunPath();
+ /** Returns true if the ELF file targets a MIPS CPU. */
+ bool IsMIPS() const;
+
/** Print human-readable information about the ELF file. */
void PrintInfo(std::ostream& os) const;
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 1a31ae4af..aa968dc38 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -22,6 +22,7 @@
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
+#include "cmValue.h"
#include "cmake.h"
class cmSourceFile;
@@ -254,7 +255,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
void cmExportBuildFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
+ cmGeneratorTarget const* depender, cmGeneratorTarget* dependee)
{
// The target is not in the export.
if (!this->AppendMode) {
@@ -321,7 +322,7 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg,
}
void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
@@ -344,7 +345,7 @@ void cmExportBuildFileGenerator::ComplainAboutMissingTarget(
}
std::string cmExportBuildFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 264494dc5..244f526db 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -60,11 +60,11 @@ protected:
cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
- void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee,
+ void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
std::vector<std::string> const& namespaces);
/** Fill in properties indicating built file locations. */
@@ -73,7 +73,7 @@ protected:
cmGeneratorTarget* target,
ImportPropertyMap& properties);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 352eaf291..63440a317 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -282,6 +282,7 @@ static bool HandlePackage(std::vector<std::string> const& args,
// CMP0090 decides both the default and what variable changes it.
switch (mf.GetPolicyStatus(cmPolicies::CMP0090)) {
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// Default is to export, but can be disabled.
if (mf.IsOn("CMAKE_EXPORT_NO_PACKAGE_REGISTRY")) {
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index dd611de6b..8ca9a66cd 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -21,13 +21,12 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetExport.h"
+#include "cmValue.h"
static std::string cmExportFileGeneratorEscape(std::string const& str)
{
@@ -123,10 +122,10 @@ void cmExportFileGenerator::GenerateImportConfig(
}
void cmExportFileGenerator::PopulateInterfaceProperty(
- const std::string& propName, cmGeneratorTarget* target,
+ const std::string& propName, cmGeneratorTarget const* target,
ImportPropertyMap& properties)
{
- cmProp input = target->GetProperty(propName);
+ cmValue input = target->GetProperty(propName);
if (input) {
properties[propName] = *input;
}
@@ -134,11 +133,11 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
void cmExportFileGenerator::PopulateInterfaceProperty(
const std::string& propName, const std::string& outputName,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmProp input = target->GetProperty(propName);
+ cmValue input = target->GetProperty(propName);
if (input) {
if (input->empty()) {
// Set to empty
@@ -168,14 +167,14 @@ void cmExportFileGenerator::GenerateRequiredCMakeVersion(
}
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
if (!target->IsLinkable()) {
return false;
}
- cmProp input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
+ cmValue input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
if (input) {
std::string prepro =
cmGeneratorExpression::Preprocess(*input, preprocessRule);
@@ -196,7 +195,7 @@ static bool isSubDirectory(std::string const& a, std::string const& b)
}
static bool checkInterfaceDirs(const std::string& prepro,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
const std::string& prop)
{
std::string const& installDir =
@@ -335,14 +334,14 @@ static void prefixItems(std::string& exportDirs)
}
void cmExportFileGenerator::PopulateSourcesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_SOURCES";
- cmProp input = gt->GetProperty(propName);
+ cmValue input = gt->GetProperty(propName);
if (!input) {
return;
@@ -366,19 +365,20 @@ void cmExportFileGenerator::PopulateSourcesInterface(
}
void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_INCLUDE_DIRECTORIES";
- cmProp input = target->GetProperty(propName);
+ cmValue input = target->GetProperty(propName);
cmGeneratorExpression ge;
std::string dirs = cmGeneratorExpression::Preprocess(
- tei->InterfaceIncludeDirectories, preprocessRule, true);
+ cmJoin(target->Target->GetInstallIncludeDirectoriesEntries(), ";"),
+ preprocessRule, true);
this->ReplaceInstallPrefix(dirs);
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
std::string exportDirs =
@@ -424,14 +424,14 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
}
void cmExportFileGenerator::PopulateLinkDependsInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_LINK_DEPENDS";
- cmProp input = gt->GetProperty(propName);
+ cmValue input = gt->GetProperty(propName);
if (!input) {
return;
@@ -455,14 +455,14 @@ void cmExportFileGenerator::PopulateLinkDependsInterface(
}
void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
- cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmGeneratorTarget const* gt,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
- cmGeneratorTarget* gt = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char* propName = "INTERFACE_LINK_DIRECTORIES";
- cmProp input = gt->GetProperty(propName);
+ cmValue input = gt->GetProperty(propName);
if (!input) {
return;
@@ -486,7 +486,7 @@ void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
}
void cmExportFileGenerator::PopulateInterfaceProperty(
- const std::string& propName, cmGeneratorTarget* target,
+ const std::string& propName, cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
@@ -497,7 +497,7 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
std::set<std::string>& ifaceProperties)
{
- cmProp p = tgt->GetProperty(prop);
+ cmValue p = tgt->GetProperty(prop);
if (!p) {
return;
}
@@ -505,7 +505,7 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
ifaceProperties.insert(content.begin(), content.end());
}
-void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
+void getCompatibleInterfaceProperties(cmGeneratorTarget const* target,
std::set<std::string>& ifaceProperties,
const std::string& config)
{
@@ -544,7 +544,7 @@ void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
}
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
- cmGeneratorTarget* gtarget, ImportPropertyMap& properties)
+ cmGeneratorTarget const* gtarget, ImportPropertyMap& properties)
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
properties);
@@ -596,7 +596,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(
}
bool cmExportFileGenerator::AddTargetNamespace(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets)
{
cmGeneratorTarget::TargetOrString resolved =
@@ -627,7 +627,7 @@ bool cmExportFileGenerator::AddTargetNamespace(
}
void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets, FreeTargetsReplace replace)
{
if (replace == NoReplaceFreeTargets) {
@@ -654,7 +654,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
}
void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets)
{
std::string::size_type pos = 0;
@@ -744,7 +744,7 @@ void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/)
void cmExportFileGenerator::SetImportLinkInterface(
const std::string& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget* target, ImportPropertyMap& properties,
+ cmGeneratorTarget const* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets)
{
// Add the transitive link dependencies for this configuration.
@@ -761,12 +761,12 @@ void cmExportFileGenerator::SetImportLinkInterface(
return;
}
- cmProp propContent;
+ cmValue propContent;
- if (cmProp prop_suffixed =
+ if (cmValue prop_suffixed =
target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
propContent = prop_suffixed;
- } else if (cmProp prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
+ } else if (cmValue prop = target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
propContent = prop;
} else {
return;
@@ -854,7 +854,7 @@ void cmExportFileGenerator::SetImportDetailProperties(
cmGeneratorTarget::ManagedType::Native) {
std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
std::string propval;
- if (cmProp p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ if (cmValue p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
propval = *p;
} else if (target->IsCSharpOnly()) {
// C# projects do not have the /clr flag, so we set the property
@@ -880,7 +880,7 @@ static std::string const& asString(cmLinkItem const& l)
template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
- std::string const& suffix, cmGeneratorTarget* target,
+ std::string const& suffix, cmGeneratorTarget const* target,
const std::string& propName, std::vector<T> const& entries,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets,
ImportLinkPropertyTargetNames targetNames)
@@ -917,20 +917,20 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Protect that file against use with older CMake versions.
/* clang-format off */
os << "# Generated by CMake\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
+ os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.6)\n"
<< " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "endif()\n";
/* clang-format on */
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.19 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.20 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6...3.19)\n";
+ << "cmake_policy(VERSION 2.6...3.20)\n";
/* clang-format on */
}
@@ -1211,11 +1211,11 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
}
bool cmExportFileGenerator::PopulateExportProperties(
- cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ cmGeneratorTarget const* gte, ImportPropertyMap& properties,
std::string& errorMessage)
{
const auto& targetProperties = gte->Target->GetProperties();
- if (cmProp exportProperties =
+ if (cmValue exportProperties =
targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
for (auto& prop : cmExpandedList(*exportProperties)) {
/* Black list reserved properties */
@@ -1228,7 +1228,7 @@ bool cmExportFileGenerator::PopulateExportProperties(
errorMessage = e.str();
return false;
}
- cmProp propertyValue = targetProperties.GetPropertyValue(prop);
+ cmValue propertyValue = targetProperties.GetPropertyValue(prop);
if (!propertyValue) {
// Asked to export a property that isn't defined on the target. Do not
// consider this an error, there's just nothing to export.
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 45eaed04f..24e048bca 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -27,8 +27,6 @@ class cmGeneratorTarget;
CMake_VERSION_MINOR) "." STRINGIFY(CMake_VERSION_PATCH) \
: #major "." #minor ".0")
-class cmTargetExport;
-
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
*
@@ -108,7 +106,7 @@ protected:
};
template <typename T>
void SetImportLinkProperty(std::string const& suffix,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
const std::string& propName,
std::vector<T> const& entries,
ImportPropertyMap& properties,
@@ -127,44 +125,45 @@ protected:
* export set. */
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) = 0;
- void PopulateInterfaceProperty(const std::string&, cmGeneratorTarget* target,
+ void PopulateInterfaceProperty(const std::string&,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
bool PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget* target, cmGeneratorExpression::PreprocessContext,
+ cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateInterfaceProperty(const std::string& propName,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
ImportPropertyMap& properties);
- void PopulateCompatibleInterfaceProperties(cmGeneratorTarget* target,
+ void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
ImportPropertyMap& properties);
virtual void GenerateInterfaceProperties(
cmGeneratorTarget const* target, std::ostream& os,
const ImportPropertyMap& properties);
void PopulateIncludeDirectoriesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateSourcesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateLinkDirectoriesInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateLinkDependsInterface(
- cmTargetExport* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void SetImportLinkInterface(
const std::string& config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
- cmGeneratorTarget* target, ImportPropertyMap& properties,
+ cmGeneratorTarget const* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
enum FreeTargetsReplace
@@ -174,14 +173,14 @@ protected:
};
void ResolveTargetsInGeneratorExpressions(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
- bool PopulateExportProperties(cmGeneratorTarget* gte,
+ bool PopulateExportProperties(cmGeneratorTarget const* gte,
ImportPropertyMap& properties,
std::string& errorMessage);
@@ -205,20 +204,20 @@ protected:
private:
void PopulateInterfaceProperty(const std::string&, const std::string&,
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
- bool AddTargetNamespace(std::string& input, cmGeneratorTarget* target,
+ bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets);
void ResolveTargetsInGeneratorExpression(
- std::string& input, cmGeneratorTarget* target,
+ std::string& input, cmGeneratorTarget const* target,
std::vector<std::string>& missingTargets);
virtual void ReplaceInstallPrefix(std::string& input);
- virtual std::string InstallNameDir(cmGeneratorTarget* target,
+ virtual std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) = 0;
};
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 3c69c5001..e9ac8752f 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
+#include "cmValue.h"
cmExportInstallFileGenerator::cmExportInstallFileGenerator(
cmInstallExportGenerator* iegen)
@@ -85,8 +86,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
ImportPropertyMap properties;
this->PopulateIncludeDirectoriesInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
- this->PopulateSourcesInterface(te, cmGeneratorExpression::InstallInterface,
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
cmGeneratorExpression::InstallInterface,
@@ -110,9 +111,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateLinkDirectoriesInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
this->PopulateLinkDependsInterface(
- te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
+ gt, cmGeneratorExpression::InstallInterface, properties, missingTargets);
std::string errorMessage;
if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
@@ -447,7 +448,7 @@ cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
+ cmGeneratorTarget const* depender, cmGeneratorTarget* dependee)
{
const std::string name = dependee->GetName();
cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator();
@@ -499,7 +500,7 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg,
}
void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
- cmGeneratorTarget* depender, cmGeneratorTarget* dependee,
+ cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles)
{
std::ostringstream e;
@@ -521,7 +522,7 @@ void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
}
std::string cmExportInstallFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 2d8de9d83..5cec2e05e 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -63,13 +63,13 @@ protected:
cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
- cmGeneratorTarget* depender,
+ cmGeneratorTarget const* depender,
cmGeneratorTarget* dependee) override;
void ReplaceInstallPrefix(std::string& input) override;
- void ComplainAboutMissingTarget(cmGeneratorTarget* depender,
- cmGeneratorTarget* dependee,
+ void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
+ cmGeneratorTarget const* dependee,
std::vector<std::string> const& exportFiles);
std::pair<std::vector<std::string>, std::string> FindNamespaces(
@@ -94,7 +94,7 @@ protected:
ImportPropertyMap& properties,
std::set<std::string>& importedLocations);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
cmInstallExportGenerator* IEGen;
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 7f31dd218..8aec12b66 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -14,12 +14,12 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
+#include "cmValue.h"
#include "cmake.h"
class cmListFileBacktrace;
@@ -96,7 +96,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename,
// Handle simple output name changes. This command is
// deprecated so we do not support full target name
// translation (which requires per-configuration info).
- if (cmProp outname = libtgt->GetProperty("OUTPUT_NAME")) {
+ if (cmValue outname = libtgt->GetProperty("OUTPUT_NAME")) {
lib = *outname;
}
}
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cac60e14a..cbe3c4dc7 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -13,10 +13,10 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
+#include "cmValue.h"
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
@@ -60,7 +60,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
const std::string& propName, cmGeneratorTarget const* tgt,
std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
{
- cmProp prop = tgt->GetProperty(propName);
+ cmValue prop = tgt->GetProperty(propName);
if (!prop) {
return std::string();
}
@@ -126,7 +126,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
}
std::string cmExportTryCompileFileGenerator::InstallNameDir(
- cmGeneratorTarget* target, const std::string& config)
+ cmGeneratorTarget const* target, const std::string& config)
{
std::string install_name_dir;
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 6bf5781e8..127b8df15 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -36,7 +36,8 @@ protected:
{
}
void HandleMissingTarget(std::string&, std::vector<std::string>&,
- cmGeneratorTarget*, cmGeneratorTarget*) override
+ cmGeneratorTarget const*,
+ cmGeneratorTarget*) override
{
}
@@ -44,7 +45,7 @@ protected:
ImportPropertyMap& properties,
std::set<const cmGeneratorTarget*>& emitted);
- std::string InstallNameDir(cmGeneratorTarget* target,
+ std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) override;
private:
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index df1426104..e2c54d77e 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -16,12 +16,12 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -396,8 +396,8 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
CbpUnit& cbpUnit = allFiles[fullPath];
cbpUnit.Targets.push_back(target.get());
}
- }
- default: // intended fallthrough
+ } break;
+ default:
break;
}
}
@@ -499,12 +499,12 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
if (target->GetType() == cmStateEnums::EXECUTABLE) {
// Determine the directory where the executable target is created, and
// set the working directory to this dir.
- cmProp runtimeOutputDir =
+ cmValue runtimeOutputDir =
makefile->GetDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
if (runtimeOutputDir) {
workingDir = *runtimeOutputDir;
} else {
- cmProp executableOutputDir =
+ cmValue executableOutputDir =
makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
if (executableOutputDir) {
workingDir = *executableOutputDir;
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 549b08b4e..9e8ac5cf0 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -208,7 +208,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
case cmStateEnums::MODULE_LIBRARY: {
projectType = "Dynamic Library";
} break;
- default: // intended fallthrough
+ default:
break;
}
@@ -233,8 +233,8 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
otherFiles.insert(fullPath);
}
}
- }
- default: // intended fallthrough
+ } break;
+ default:
break;
}
return projectType;
@@ -556,7 +556,8 @@ void cmExtraCodeLiteGenerator::CreateNewProjectFile(
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
visualname = "lib" + targetName;
- default: // intended fallthrough
+ break;
+ default:
break;
}
xml.Attribute("Name", visualname);
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 672089c73..d9d5a4b50 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -19,13 +19,13 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmXMLWriter.h"
#include "cmake.h"
@@ -189,7 +189,7 @@ void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile()
}
fout << "eclipse.preferences.version=1\n";
- cmProp encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING");
+ cmValue encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING");
if (encoding) {
fout << "encoding/<project>=" << *encoding << '\n';
}
@@ -244,7 +244,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
- cmProp cacheValue = lg.GetState()->GetInitializedCacheValue(cacheEntryName);
+ cmValue cacheValue = lg.GetState()->GetInitializedCacheValue(cacheEntryName);
// now we have both, decide which one to use
std::string valueToUse;
@@ -415,7 +415,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
xml.Element("nature", n);
}
- if (cmProp extraNaturesProp =
+ if (cmValue extraNaturesProp =
mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) {
std::vector<std::string> extraNatures = cmExpandedList(*extraNaturesProp);
for (std::string const& n : extraNatures) {
@@ -754,7 +754,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
emitted.clear();
for (const auto& lgen : this->GlobalGenerator->GetLocalGenerators()) {
- if (cmProp cdefs =
+ if (cmValue cdefs =
lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
std::vector<std::string> defs;
@@ -793,7 +793,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
}
// add system defined c macros
- cmProp cDefs =
+ cmValue cDefs =
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS");
if (this->CEnabled && cDefs) {
// Expand the list.
@@ -825,7 +825,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
}
}
// add system defined c++ macros
- cmProp cxxDefs =
+ cmValue cxxDefs =
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS");
if (this->CXXEnabled && cxxDefs) {
// Expand the list.
@@ -1032,7 +1032,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement(); // storageModule
// Append additional cproject contents without applying any XML formatting
- if (cmProp extraCProjectContents =
+ if (cmValue extraCProjectContents =
mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) {
fout << *extraCProjectContents;
}
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 9153119c4..eec43c473 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -13,11 +13,11 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmExtraKateGenerator::cmExtraKateGenerator() = default;
@@ -128,7 +128,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator& lg,
// only add the "edit_cache" target if it's not ccmake, because
// this will not work within the IDE
if (targetName == "edit_cache") {
- cmProp editCommand =
+ cmValue editCommand =
localGen->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
if (!editCommand ||
strstr(editCommand->c_str(), "ccmake") != nullptr) {
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 52965bb57..fa93b04d2 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -17,11 +17,11 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
/*
@@ -364,12 +364,12 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = source->GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = source->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = source->GetProperty(COMPILE_OPTIONS)) {
+ if (cmValue coptions = source->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
@@ -393,14 +393,14 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
// Add preprocessor definitions for this target and configuration.
lg->GetTargetDefines(target, config, language, defines);
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- if (cmProp compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
+ if (cmValue compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
lg->AppendDefines(
defines, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS));
}
std::string defPropName =
cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
- if (cmProp config_compile_defs = source->GetProperty(defPropName)) {
+ if (cmValue config_compile_defs = source->GetProperty(defPropName)) {
lg->AppendDefines(
defines,
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
@@ -425,7 +425,7 @@ std::string cmExtraSublimeTextGenerator::ComputeIncludes(
// Add include directories for this source file
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
+ if (cmValue cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
lg->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES),
*source);
@@ -445,7 +445,7 @@ bool cmExtraSublimeTextGenerator::Open(const std::string& bindir,
const std::string& projectName,
bool dryRun)
{
- cmProp sublExecutable =
+ cmValue sublExecutable =
this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition(
"CMAKE_SUBLIMETEXT_EXECUTABLE");
if (!sublExecutable) {
diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx
index ddae5273b..ba38ef798 100644
--- a/Source/cmFileAPICache.cxx
+++ b/Source/cmFileAPICache.cxx
@@ -10,8 +10,8 @@
#include <cm3p/json/value.h>
#include "cmFileAPI.h"
-#include "cmProperty.h"
#include "cmState.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -95,7 +95,7 @@ Json::Value Cache::DumpEntryProperty(std::string const& name,
{
Json::Value property = Json::objectValue;
property["name"] = prop;
- cmProp p = this->State->GetCacheEntryProperty(name, prop);
+ cmValue p = this->State->GetCacheEntryProperty(name, prop);
property["value"] = p ? *p : "";
return property;
}
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index a2b5460c1..147181e3f 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -41,7 +41,6 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
@@ -53,6 +52,7 @@
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmTargetExport.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -813,8 +813,7 @@ Json::Value CodemodelConfig::DumpProject(Project& p)
Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
{
Json::Value minimumCMakeVersion;
- if (std::string const* def =
- s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+ if (cmValue def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
minimumCMakeVersion = Json::objectValue;
minimumCMakeVersion["string"] = *def;
}
@@ -1188,10 +1187,10 @@ void Target::ProcessLanguage(std::string const& lang)
{
CompileData& cd = this->CompileDataMap[lang];
cd.Language = lang;
- if (cmProp sysrootCompile =
+ if (cmValue sysrootCompile =
this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
cd.Sysroot = *sysrootCompile;
- } else if (cmProp sysroot =
+ } else if (cmValue sysroot =
this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
cd.Sysroot = *sysroot;
}
@@ -1260,7 +1259,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf)
fd.Language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
std::string flags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
fd.Flags.emplace_back(std::move(flags), JBTIndex());
}
@@ -1354,7 +1353,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf)
std::set<std::string> configFileDefines;
const std::string defPropName =
"COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config);
- if (cmProp config_defs = sf->GetProperty(defPropName)) {
+ if (cmValue config_defs = sf->GetProperty(defPropName)) {
lg->AppendDefines(
configFileDefines,
genexInterpreter.Evaluate(*config_defs, COMPILE_DEFINITIONS));
@@ -1740,10 +1739,10 @@ Json::Value Target::DumpLink()
link["commandFragments"] = std::move(commandFragments);
}
}
- if (cmProp sysrootLink =
+ if (cmValue sysrootLink =
this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
link["sysroot"] = this->DumpSysroot(*sysrootLink);
- } else if (cmProp sysroot =
+ } else if (cmValue sysroot =
this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
link["sysroot"] = this->DumpSysroot(*sysroot);
}
@@ -1869,7 +1868,7 @@ Json::Value Target::DumpDependency(cmTargetDepend const& td)
Json::Value Target::DumpFolder()
{
Json::Value folder;
- if (cmProp f = this->GT->GetProperty("FOLDER")) {
+ if (cmValue f = this->GT->GetProperty("FOLDER")) {
folder = Json::objectValue;
folder["name"] = *f;
}
diff --git a/Source/cmFileAPIToolchains.cxx b/Source/cmFileAPIToolchains.cxx
index 722c1145e..b3540c97b 100644
--- a/Source/cmFileAPIToolchains.cxx
+++ b/Source/cmFileAPIToolchains.cxx
@@ -11,9 +11,9 @@
#include "cmFileAPI.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -136,7 +136,7 @@ void Toolchains::DumpToolchainVariable(cmMakefile const* mf,
object[variable.ObjectKey] = jsonArray;
}
} else {
- cmProp def = mf->GetDefinition(variableName);
+ cmValue def = mf->GetDefinition(variableName);
if (def) {
object[variable.ObjectKey] = *def;
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 0ad59c7b5..fd0595d88 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -31,6 +31,7 @@
#include "cmArgumentParser.h"
#include "cmCMakePath.h"
#include "cmCryptoHash.h"
+#include "cmELF.h"
#include "cmExecutionStatus.h"
#include "cmFSPermissions.h"
#include "cmFileCopier.h"
@@ -46,7 +47,6 @@
#include "cmMessageType.h"
#include "cmNewLineStyle.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmRuntimeDependencyArchive.h"
#include "cmState.h"
@@ -54,6 +54,7 @@
#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
+#include "cmValue.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"
@@ -64,41 +65,8 @@
# include "cmFileLockResult.h"
#endif
-#if defined(CMake_USE_ELF_PARSER)
-# include "cmELF.h"
-#endif
-
-#if defined(_WIN32)
-# include <windows.h>
-#endif
-
namespace {
-#if defined(_WIN32)
-// libcurl doesn't support file:// urls for unicode filenames on Windows.
-// Convert string from UTF-8 to ACP if this is a file:// URL.
-std::string fix_file_url_windows(const std::string& url)
-{
- std::string ret = url;
- if (strncmp(url.c_str(), "file://", 7) == 0) {
- std::wstring wurl = cmsys::Encoding::ToWide(url);
- if (!wurl.empty()) {
- int mblen =
- WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, NULL, 0, NULL, NULL);
- if (mblen > 0) {
- std::vector<char> chars(mblen);
- mblen = WideCharToMultiByte(CP_ACP, 0, wurl.c_str(), -1, &chars[0],
- mblen, NULL, NULL);
- if (mblen > 0) {
- ret = &chars[0];
- }
- }
- }
- }
- return ret;
-}
-#endif
-
bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
cmExecutionStatus& status)
{
@@ -672,8 +640,9 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse,
case cmPolicies::NEW:
g.RecurseThroughSymlinksOff();
break;
- case cmPolicies::OLD:
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
g.RecurseThroughSymlinksOn();
break;
}
@@ -1242,8 +1211,12 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
return false;
}
-#if defined(CMake_USE_ELF_PARSER)
cmELF elf(fileNameArg.c_str());
+ if (!elf) {
+ status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
+ "\" that is not a valid ELF file."));
+ return false;
+ }
if (!arguments.RPath.empty()) {
if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
@@ -1261,15 +1234,6 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
}
return true;
-#else
- std::string error = "ELF parser not available on this platform.";
- if (arguments.Error.empty()) {
- status.SetError(error);
- return false;
- }
- status.GetMakefile().AddDefinition(arguments.Error, error);
- return true;
-#endif
}
bool HandleInstallCommand(std::vector<std::string> const& args,
@@ -1803,7 +1767,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
std::string logVar;
std::string statusVar;
bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY");
- cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO");
+ cmValue cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO");
std::string netrc_level =
status.GetMakefile().GetSafeDefinition("CMAKE_NETRC");
std::string netrc_file =
@@ -1858,7 +1822,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmValue(*i);
} else {
status.SetError("DOWNLOAD missing file value for TLS_CAINFO.");
return false;
@@ -1984,9 +1948,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
}
}
-# if defined(_WIN32)
- url = fix_file_url_windows(url);
-# endif
+ url = cmCurlFixFileURL(url);
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -2025,7 +1987,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
// check to see if a CAINFO file has been specified
// command arg comes first
- std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo));
+ std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo);
if (!cainfo_err.empty()) {
status.SetError(cainfo_err);
return false;
@@ -2191,7 +2153,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
std::string statusVar;
bool showProgress = false;
bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY");
- cmProp cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO");
+ cmValue cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO");
std::string userpwd;
std::string netrc_level =
status.GetMakefile().GetSafeDefinition("CMAKE_NETRC");
@@ -2244,7 +2206,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmValue(*i);
} else {
status.SetError("UPLOAD missing file value for TLS_CAINFO.");
return false;
@@ -2300,9 +2262,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
unsigned long file_size = cmsys::SystemTools::FileLength(filename);
-# if defined(_WIN32)
- url = fix_file_url_windows(url);
-# endif
+ url = cmCurlFixFileURL(url);
::CURL* curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -2345,7 +2305,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
// check to see if a CAINFO file has been specified
// command arg comes first
- std::string const& cainfo_err = cmCurlSetCAInfo(curl, cmToCStr(cainfo));
+ std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo);
if (!cainfo_err.empty()) {
status.SetError(cainfo_err);
return false;
@@ -3210,9 +3170,12 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
archive.GetUnresolvedPaths().begin(),
archive.GetUnresolvedPaths().end());
} else {
- auto it = archive.GetUnresolvedPaths().begin();
- assert(it != archive.GetUnresolvedPaths().end());
- status.SetError(cmStrCat("Could not resolve file ", *it));
+ std::ostringstream e;
+ e << "Could not resolve runtime dependencies:";
+ for (auto const& path : archive.GetUnresolvedPaths()) {
+ e << "\n " << path;
+ }
+ status.SetError(e.str());
cmSystemTools::SetFatalErrorOccured();
return false;
}
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 237d234f8..63a4274c1 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -10,9 +10,9 @@
#include "cmFSPermissions.h"
#include "cmFileTimes.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#ifdef _WIN32
# include "cmsys/FStream.hxx"
@@ -172,7 +172,7 @@ void cmFileCopier::DefaultDirectoryPermissions()
bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
{
// check if default dir creation permissions were set
- cmProp default_dir_install_permissions = this->Makefile->GetDefinition(
+ cmValue default_dir_install_permissions = this->Makefile->GetDefinition(
"CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
if (cmNonempty(default_dir_install_permissions)) {
std::vector<std::string> items =
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
index 217d58d28..ee9872d9d 100644
--- a/Source/cmFileCopier.h
+++ b/Source/cmFileCopier.h
@@ -67,8 +67,9 @@ protected:
bool InstallSymlinkChain(std::string& fromFile, std::string& toFile);
bool InstallSymlink(const std::string& fromFile, const std::string& toFile);
- bool InstallFile(const std::string& fromFile, const std::string& toFile,
- MatchProperties match_properties);
+ virtual bool InstallFile(const std::string& fromFile,
+ const std::string& toFile,
+ MatchProperties match_properties);
bool InstallDirectory(const std::string& source,
const std::string& destination,
MatchProperties match_properties);
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
index c89be9628..9bfbd135c 100644
--- a/Source/cmFileInstaller.cxx
+++ b/Source/cmFileInstaller.cxx
@@ -3,7 +3,12 @@
#include "cmFileInstaller.h"
+#include <map>
#include <sstream>
+#include <utility>
+
+#include <cm/string_view>
+#include <cmext/string_view>
#include "cm_sys_stat.h"
@@ -12,12 +17,14 @@
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
using namespace cmFSPermissions;
cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)
: cmFileCopier(status, "INSTALL")
, InstallType(cmInstallType_FILES)
+ , InstallMode(cmInstallMode::COPY)
, Optional(false)
, MessageAlways(false)
, MessageLazy(false)
@@ -82,6 +89,93 @@ bool cmFileInstaller::Install(const std::string& fromFile,
return this->cmFileCopier::Install(fromFile, toFile);
}
+bool cmFileInstaller::InstallFile(const std::string& fromFile,
+ const std::string& toFile,
+ MatchProperties match_properties)
+{
+ if (this->InstallMode == cmInstallMode::COPY) {
+ return this->cmFileCopier::InstallFile(fromFile, toFile, match_properties);
+ }
+
+ std::string newFromFile;
+
+ if (this->InstallMode == cmInstallMode::REL_SYMLINK ||
+ this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::SYMLINK ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // Try to get a relative path.
+ std::string toDir = cmSystemTools::GetParentDirectory(toFile);
+ newFromFile = cmSystemTools::ForceToRelativePath(toDir, fromFile);
+
+ // Double check that we can restore the original path.
+ std::string reassembled =
+ cmSystemTools::CollapseFullPath(newFromFile, toDir);
+ if (!cmSystemTools::ComparePath(reassembled, fromFile)) {
+ if (this->InstallMode == cmInstallMode::SYMLINK ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // User does not mind, silently proceed with absolute path.
+ newFromFile = fromFile;
+ } else if (this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY) {
+ // User expects a relative symbolic link or a copy.
+ // Since an absolute symlink won't do, copy instead.
+ return this->cmFileCopier::InstallFile(fromFile, toFile,
+ match_properties);
+ } else {
+ // We cannot meet user's expectation (REL_SYMLINK)
+ auto e = cmStrCat(this->Name,
+ " cannot determine relative path for symlink to \"",
+ newFromFile, "\" at \"", toFile, "\".");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+ } else {
+ newFromFile = fromFile; // stick with absolute path
+ }
+
+ // Compare the symlink value to that at the destination if not
+ // always installing.
+ bool copy = true;
+ if (!this->Always) {
+ std::string oldSymlinkTarget;
+ if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
+ if (newFromFile == oldSymlinkTarget) {
+ copy = false;
+ }
+ }
+ }
+
+ // Inform the user about this file installation.
+ this->ReportCopy(toFile, TypeLink, copy);
+
+ if (copy) {
+ // Remove the destination file so we can always create the symlink.
+ cmSystemTools::RemoveFile(toFile);
+
+ // Create destination directory if it doesn't exist
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
+
+ // Create the symlink.
+ if (!cmSystemTools::CreateSymlink(newFromFile, toFile)) {
+ if (this->InstallMode == cmInstallMode::ABS_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::REL_SYMLINK_OR_COPY ||
+ this->InstallMode == cmInstallMode::SYMLINK_OR_COPY) {
+ // Failed to create a symbolic link, fall back to copying.
+ return this->cmFileCopier::InstallFile(newFromFile, toFile,
+ match_properties);
+ }
+
+ auto e = cmStrCat(this->Name, " cannot create symlink to \"",
+ newFromFile, "\" at \"", toFile,
+ "\": ", cmSystemTools::GetLastSystemError(), "\".");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+
+ return true;
+}
+
void cmFileInstaller::DefaultFilePermissions()
{
this->cmFileCopier::DefaultFilePermissions();
@@ -141,6 +235,31 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
return false;
}
+ static const std::map<cm::string_view, cmInstallMode> install_mode_dict{
+ { "ABS_SYMLINK"_s, cmInstallMode::ABS_SYMLINK },
+ { "ABS_SYMLINK_OR_COPY"_s, cmInstallMode::ABS_SYMLINK_OR_COPY },
+ { "REL_SYMLINK"_s, cmInstallMode::REL_SYMLINK },
+ { "REL_SYMLINK_OR_COPY"_s, cmInstallMode::REL_SYMLINK_OR_COPY },
+ { "SYMLINK"_s, cmInstallMode::SYMLINK },
+ { "SYMLINK_OR_COPY"_s, cmInstallMode::SYMLINK_OR_COPY }
+ };
+
+ std::string install_mode;
+ cmSystemTools::GetEnv("CMAKE_INSTALL_MODE", install_mode);
+ if (install_mode.empty() || install_mode == "COPY"_s) {
+ this->InstallMode = cmInstallMode::COPY;
+ } else {
+ auto it = install_mode_dict.find(install_mode);
+ if (it != install_mode_dict.end()) {
+ this->InstallMode = it->second;
+ } else {
+ auto e = cmStrCat("Unrecognized value '", install_mode,
+ "' for environment variable CMAKE_INSTALL_MODE");
+ this->Status.SetError(e);
+ return false;
+ }
+ }
+
return true;
}
diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h
index 3a905d320..3f6bd4542 100644
--- a/Source/cmFileInstaller.h
+++ b/Source/cmFileInstaller.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmFileCopier.h"
+#include "cmInstallMode.h"
#include "cmInstallType.h"
class cmExecutionStatus;
@@ -19,6 +20,7 @@ struct cmFileInstaller : public cmFileCopier
protected:
cmInstallType InstallType;
+ cmInstallMode InstallMode;
bool Optional;
bool MessageAlways;
bool MessageLazy;
@@ -35,7 +37,8 @@ protected:
bool ReportMissing(const std::string& fromFile) override;
bool Install(const std::string& fromFile,
const std::string& toFile) override;
-
+ bool InstallFile(const std::string& fromFile, const std::string& toFile,
+ MatchProperties match_properties) override;
bool Parse(std::vector<std::string> const& args) override;
enum
{
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 1038ac29e..a123e4408 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -13,13 +13,13 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
class cmExecutionStatus;
@@ -301,9 +301,9 @@ void cmFindBase::FillUserGuessPath()
bool cmFindBase::CheckForVariableDefined()
{
- if (cmProp value = this->Makefile->GetDefinition(this->VariableName)) {
+ if (cmValue value = this->Makefile->GetDefinition(this->VariableName)) {
cmState* state = this->Makefile->GetState();
- cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName);
+ cmValue cacheEntry = state->GetCacheEntryValue(this->VariableName);
bool found = !cmIsNOTFOUND(*value);
bool cached = cacheEntry != nullptr;
auto cacheType = cached ? state->GetCacheEntryType(this->VariableName)
@@ -311,7 +311,7 @@ bool cmFindBase::CheckForVariableDefined()
if (cached && cacheType != cmStateEnums::UNINITIALIZED) {
this->VariableType = cacheType;
- if (const auto* hs =
+ if (const auto& hs =
state->GetCacheEntryProperty(this->VariableName, "HELPSTRING")) {
this->VariableDocumentation = *hs;
}
@@ -336,7 +336,7 @@ void cmFindBase::NormalizeFindResult()
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0125) ==
cmPolicies::NEW) {
// ensure the path returned by find_* command is absolute
- const auto* existingValue =
+ const auto& existingValue =
this->Makefile->GetDefinition(this->VariableName);
std::string value;
if (!existingValue->empty()) {
@@ -358,8 +358,8 @@ void cmFindBase::NormalizeFindResult()
// value.
if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) {
this->Makefile->GetCMakeInstance()->AddCacheEntry(
- this->VariableName, value.c_str(),
- this->VariableDocumentation.c_str(), this->VariableType);
+ this->VariableName, value, this->VariableDocumentation.c_str(),
+ this->VariableType);
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
cmPolicies::NEW) {
if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index d2f96197b..bdc920772 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -11,9 +11,9 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL");
@@ -183,7 +183,7 @@ void cmFindCommon::SelectDefaultSearchModes()
};
for (auto const& path : search_paths) {
- cmProp def = this->Makefile->GetDefinition(path.second);
+ cmValue def = this->Makefile->GetDefinition(path.second);
if (def) {
path.first = !cmIsOn(*def);
}
@@ -203,11 +203,11 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
return;
}
- cmProp sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
- cmProp sysrootCompile =
+ cmValue sysroot = this->Makefile->GetDefinition("CMAKE_SYSROOT");
+ cmValue sysrootCompile =
this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE");
- cmProp sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
- cmProp rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
+ cmValue sysrootLink = this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK");
+ cmValue rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
const bool noSysroot = !cmNonempty(sysroot);
const bool noCompileSysroot = !cmNonempty(sysrootCompile);
const bool noLinkSysroot = !cmNonempty(sysrootLink);
@@ -234,7 +234,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
cmSystemTools::ConvertToUnixSlashes(r);
}
- cmProp stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
+ cmValue stagePrefix = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX");
// Copy the original set of unrooted paths.
std::vector<std::string> unrootedPaths = paths;
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 0cbe63773..ff04bab06 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -12,11 +12,11 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmExecutionStatus;
@@ -46,7 +46,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
// add custom lib<qual> paths instead of using fixed lib32, lib64 or
// libx32
- if (cmProp customLib = this->Makefile->GetDefinition(
+ if (cmValue customLib = this->Makefile->GetDefinition(
"CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX")) {
this->AddArchitecturePaths(customLib->c_str());
}
@@ -247,7 +247,7 @@ struct cmFindLibraryHelper
cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr);
this->DebugSearches.FailedAt(path, regexName);
}
- };
+ }
void DebugLibraryFound(std::string const& name, std::string const& path)
{
@@ -256,9 +256,37 @@ struct cmFindLibraryHelper
cmStrCat(this->PrefixRegexStr, name, this->SuffixRegexStr);
this->DebugSearches.FoundAt(path, regexName);
}
- };
+ }
};
+namespace {
+
+std::string const& get_prefixes(cmMakefile* mf)
+{
+#ifdef _WIN32
+ static std::string defaultPrefix = ";lib";
+#else
+ static std::string defaultPrefix = "lib";
+#endif
+ cmValue prefixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
+ return (prefixProp) ? *prefixProp : defaultPrefix;
+}
+
+std::string const& get_suffixes(cmMakefile* mf)
+{
+#ifdef _WIN32
+ static std::string defaultSuffix = ".lib;.dll.a;.a";
+#elif defined(__APPLE__)
+ static std::string defaultSuffix = ".tbd;.dylib;.so;.a";
+#elif defined(__hpux)
+ static std::string defaultSuffix = ".sl;.so;.a";
+#else
+ static std::string defaultSuffix = ".so;.a";
+#endif
+ cmValue suffixProp = mf->GetDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
+ return (suffixProp) ? *suffixProp : defaultSuffix;
+}
+}
cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
cmFindBase const* base)
: Makefile(mf)
@@ -268,10 +296,9 @@ cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
this->GG = this->Makefile->GetGlobalGenerator();
// Collect the list of library name prefixes/suffixes to try.
- std::string const& prefixes_list =
- this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES");
- std::string const& suffixes_list =
- this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES");
+ std::string const& prefixes_list = get_prefixes(this->Makefile);
+ std::string const& suffixes_list = get_suffixes(this->Makefile);
+
cmExpandList(prefixes_list, this->Prefixes, true);
cmExpandList(suffixes_list, this->Suffixes, true);
this->RegexFromList(this->PrefixRegexStr, this->Prefixes);
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index fba736eed..335ebbe4e 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -25,13 +25,13 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#if defined(__HAIKU__)
@@ -137,7 +137,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
// Lookup required version of CMake.
- if (cmProp rv =
+ if (cmValue rv =
this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
unsigned int v[3] = { 0, 0, 0 };
sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]);
@@ -148,7 +148,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->DebugBuffer.clear();
// Lookup target architecture, if any.
- if (cmProp arch =
+ if (cmValue arch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) {
this->LibraryArchitecture = *arch;
}
@@ -177,7 +177,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// Check if User Package Registry should be disabled
// The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has
// priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
- if (cmProp def =
+ if (cmValue def =
this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) {
this->NoUserRegistry = !cmIsOn(*def);
} else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) {
@@ -187,7 +187,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
// Check if System Package Registry should be disabled
// The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has
// priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
- if (cmProp def = this->Makefile->GetDefinition(
+ if (cmValue def = this->Makefile->GetDefinition(
"CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) {
this->NoSystemRegistry = !cmIsOn(*def);
} else if (this->Makefile->IsOn(
@@ -201,7 +201,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
}
// Check if Sorting should be enabled
- if (cmProp so =
+ if (cmValue so =
this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {
if (*so == "NAME") {
@@ -212,7 +212,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->SortOrder = None;
}
}
- if (cmProp sd =
+ if (cmValue sd =
this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) {
this->SortDirection = (*sd == "ASC") ? Asc : Dec;
}
@@ -478,17 +478,35 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
this->VersionMaxPatch, this->VersionMaxTweak);
}
+ const std::string makePackageRequiredVar =
+ cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name);
+ const bool makePackageRequiredSet =
+ this->Makefile->IsOn(makePackageRequiredVar);
+ if (makePackageRequiredSet) {
+ if (this->Required) {
+ this->Makefile->IssueMessage(
+ MessageType::WARNING,
+ cmStrCat("for module ", this->Name,
+ " already called with REQUIRED, thus ",
+ makePackageRequiredVar, " has no effect."));
+ } else {
+ this->Required = true;
+ }
+ }
+
std::string disableFindPackageVar =
cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
if (this->Makefile->IsOn(disableFindPackageVar)) {
if (this->Required) {
this->SetError(
- cmStrCat("for module ", this->Name, " called with REQUIRED, but ",
- disableFindPackageVar,
+ cmStrCat("for module ", this->Name,
+ (makePackageRequiredSet
+ ? " was made REQUIRED with " + makePackageRequiredVar
+ : " called with REQUIRED, "),
+ " but ", disableFindPackageVar,
" is enabled. A REQUIRED package cannot be disabled."));
return false;
}
-
return true;
}
@@ -735,7 +753,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
cm::string_view value)
{
- if (cmProp old = this->Makefile->GetDefinition(var)) {
+ if (cmValue old = this->Makefile->GetDefinition(var)) {
this->OriginalDefs[var].exists = true;
this->OriginalDefs[var].value = *old;
} else {
@@ -828,7 +846,7 @@ bool cmFindPackageCommand::HandlePackageMode(
this->ConsideredConfigs.clear();
// Try to find the config file.
- cmProp def = this->Makefile->GetDefinition(this->Variable);
+ cmValue def = this->Makefile->GetDefinition(this->Variable);
// Try to load the config file if the directory is known
bool fileFound = false;
@@ -1188,7 +1206,7 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f,
void cmFindPackageCommand::AppendToFoundProperty(bool found)
{
std::vector<std::string> foundContents;
- cmProp foundProp =
+ cmValue foundProp =
this->Makefile->GetState()->GetGlobalProperty("PACKAGES_FOUND");
if (cmNonempty(foundProp)) {
cmExpandList(*foundProp, foundContents, false);
@@ -1200,7 +1218,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
}
std::vector<std::string> notFoundContents;
- cmProp notFoundProp =
+ cmValue notFoundProp =
this->Makefile->GetState()->GetGlobalProperty("PACKAGES_NOT_FOUND");
if (cmNonempty(notFoundProp)) {
cmExpandList(*notFoundProp, notFoundContents, false);
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 4845a6d09..dcb362654 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -30,6 +30,7 @@
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
class cmForEachFunctionBlocker : public cmFunctionBlocker
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 1b14d1777..70fe5374c 100644
--- a/Source/cmFortranParser.h
+++ b/Source/cmFortranParser.h
@@ -40,6 +40,8 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser);
/* Callbacks for parser. */
void cmFortranParser_Error(cmFortranParser* parser, const char* message);
void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name);
+void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
+ const char* module_name);
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename);
void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name);
@@ -99,6 +101,9 @@ public:
std::set<std::string> Provides;
std::set<std::string> Requires;
+ // Set of intrinsic modules.
+ std::set<std::string> Intrinsics;
+
// Set of files included in the translation unit.
std::set<std::string> Includes;
};
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 054a2a93e..efcc5bb2e 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -197,6 +197,19 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name)
parser->Info.Requires.insert(parser->ModName(mod_name));
}
+void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser,
+ const char* module_name)
+{
+ if (parser->InPPFalseBranch) {
+ return;
+ }
+
+ // syntax: "use, intrinsic:: module_name"
+ // requires: "module_name.mod"
+ std::string const& mod_name = cmSystemTools::LowerCase(module_name);
+ parser->Info.Intrinsics.insert(parser->ModName(mod_name));
+}
+
void cmFortranParser_RuleLineDirective(cmFortranParser* parser,
const char* filename)
{
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 217ebe5f9..c357ee145 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -37,7 +37,6 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStandardLevelResolver.h"
#include "cmState.h"
@@ -46,6 +45,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
@@ -771,8 +771,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
}
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.front().c_str(),
- compilerVersion.c_str())
+ parameters.front(), compilerVersion)
? "1"
: "0";
}
@@ -830,8 +829,7 @@ struct VersionNode : public cmGeneratorExpressionNode
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
- return cmSystemTools::VersionCompare(Op, parameters.front().c_str(),
- parameters[1].c_str())
+ return cmSystemTools::VersionCompare(Op, parameters.front(), parameters[1])
? "1"
: "0";
}
@@ -916,8 +914,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
}
if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
- cmProp loc = nullptr;
- cmProp imp = nullptr;
+ cmValue loc = nullptr;
+ cmValue imp = nullptr;
std::string suffix;
if (context->CurrentTarget->Target->GetMappedConfig(context->Config, loc,
imp, suffix)) {
@@ -927,7 +925,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
std::vector<std::string> mappedConfigs;
std::string mapProp = cmStrCat(
"MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
- if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) {
+ if (cmValue mapValue = context->CurrentTarget->GetProperty(mapProp)) {
cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs);
for (auto const& param : parameters) {
@@ -1504,7 +1502,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
std::string result;
bool haveProp = false;
- if (cmProp p = target->GetProperty(propertyName)) {
+ if (cmValue p = target->GetProperty(propertyName)) {
result = *p;
haveProp = true;
} else if (evaluatingLinkLibraries) {
@@ -1654,8 +1652,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode
std::vector<std::string> objects;
if (gt->IsImported()) {
- cmProp loc = nullptr;
- cmProp imp = nullptr;
+ cmValue loc = nullptr;
+ cmValue imp = nullptr;
std::string suffix;
if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) {
cmExpandList(*loc, objects);
@@ -1777,7 +1775,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
testedFeatures[lang].push_back(p);
if (availableFeatures.find(lang) == availableFeatures.end()) {
- const char* featuresKnown =
+ cmValue featuresKnown =
standardResolver.CompileFeaturesAvailable(lang, &error);
if (!featuresKnown) {
reportError(context, content->GetOriginalExpression(), error);
@@ -1792,7 +1790,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
for (auto const& lit : testedFeatures) {
std::vector<std::string> const& langAvailable =
availableFeatures[lit.first];
- cmProp standardDefault = context->LG->GetMakefile()->GetDefinition(
+ cmValue standardDefault = context->LG->GetMakefile()->GetDefinition(
"CMAKE_" + lit.first + "_STANDARD_DEFAULT");
for (std::string const& it : lit.second) {
if (!cm::contains(langAvailable, it)) {
@@ -1806,7 +1804,8 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
if (!standardResolver.HaveStandardAvailable(target, lit.first,
context->Config, it)) {
if (evalLL) {
- cmProp l = target->GetLanguageStandard(lit.first, context->Config);
+ cmValue l =
+ target->GetLanguageStandard(lit.first, context->Config);
if (!l) {
l = standardDefault;
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f1ef130af..8033ef544 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -58,11 +58,11 @@ const cmsys::RegularExpression FrameworkRegularExpression(
}
template <>
-cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
+cmValue cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
cmListFileBacktrace const& /* context */)
{
- return &tgt->GetSourcesProperty();
+ return tgt->GetSourcesProperty();
}
template <>
@@ -145,12 +145,10 @@ private:
class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
{
public:
- TargetPropertyEntryString(std::string propertyValue,
- cmListFileBacktrace backtrace,
+ TargetPropertyEntryString(BT<std::string> propertyValue,
cmLinkImplItem const& item = NoLinkImplItem)
: cmGeneratorTarget::TargetPropertyEntry(item)
, PropertyValue(std::move(propertyValue))
- , Backtrace(std::move(backtrace))
{
}
@@ -159,46 +157,46 @@ public:
cmGeneratorExpressionDAGChecker*,
std::string const&) const override
{
- return this->PropertyValue;
+ return this->PropertyValue.Value;
}
- cmListFileBacktrace GetBacktrace() const override { return this->Backtrace; }
- std::string const& GetInput() const override { return this->PropertyValue; }
+ cmListFileBacktrace GetBacktrace() const override
+ {
+ return this->PropertyValue.Backtrace;
+ }
+ std::string const& GetInput() const override
+ {
+ return this->PropertyValue.Value;
+ }
private:
- std::string PropertyValue;
- cmListFileBacktrace Backtrace;
+ BT<std::string> PropertyValue;
};
std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>
-CreateTargetPropertyEntry(
- const std::string& propertyValue,
- cmListFileBacktrace backtrace = cmListFileBacktrace(),
- bool evaluateForBuildsystem = false)
+CreateTargetPropertyEntry(const BT<std::string>& propertyValue,
+ bool evaluateForBuildsystem = false)
{
- if (cmGeneratorExpression::Find(propertyValue) != std::string::npos) {
- cmGeneratorExpression ge(std::move(backtrace));
+ if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) {
+ cmGeneratorExpression ge(propertyValue.Backtrace);
std::unique_ptr<cmCompiledGeneratorExpression> cge =
- ge.Parse(propertyValue);
+ ge.Parse(propertyValue.Value);
cge->SetEvaluateForBuildsystem(evaluateForBuildsystem);
return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
cm::make_unique<TargetPropertyEntryGenex>(std::move(cge)));
}
return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>(
- cm::make_unique<TargetPropertyEntryString>(propertyValue,
- std::move(backtrace)));
+ cm::make_unique<TargetPropertyEntryString>(propertyValue));
}
void CreatePropertyGeneratorExpressions(
- cmStringRange entries, cmBacktraceRange backtraces,
+ cmBTStringRange entries,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
bool evaluateForBuildsystem = false)
{
- auto btIt = backtraces.begin();
- for (auto it = entries.begin(); it != entries.end(); ++it, ++btIt) {
- items.push_back(
- CreateTargetPropertyEntry(*it, *btIt, evaluateForBuildsystem));
+ for (auto const& entry : entries) {
+ items.push_back(CreateTargetPropertyEntry(entry, evaluateForBuildsystem));
}
}
@@ -289,35 +287,27 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
this->GlobalGenerator->ComputeTargetObjectDirectory(this);
CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(),
- t->GetIncludeDirectoriesBacktraces(),
this->IncludeDirectoriesEntries);
CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(),
- t->GetCompileOptionsBacktraces(),
this->CompileOptionsEntries);
CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(),
- t->GetCompileFeaturesBacktraces(),
this->CompileFeaturesEntries);
CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(),
- t->GetCompileDefinitionsBacktraces(),
this->CompileDefinitionsEntries);
CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(),
- t->GetLinkOptionsBacktraces(),
this->LinkOptionsEntries);
CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
- t->GetLinkDirectoriesBacktraces(),
this->LinkDirectoriesEntries);
CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(),
- t->GetPrecompileHeadersBacktraces(),
this->PrecompileHeadersEntries);
CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
- t->GetSourceBacktraces(),
this->SourceEntries, true);
this->PolicyMap = t->GetPolicyMap();
@@ -332,7 +322,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
cmGeneratorTarget::~cmGeneratorTarget() = default;
-const std::string& cmGeneratorTarget::GetSourcesProperty() const
+cmValue cmGeneratorTarget::GetSourcesProperty() const
{
std::vector<std::string> values;
for (auto const& se : this->SourceEntries) {
@@ -341,7 +331,7 @@ const std::string& cmGeneratorTarget::GetSourcesProperty() const
static std::string value;
value.clear();
value = cmJoin(values, ";");
- return value;
+ return cmValue(value);
}
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
@@ -366,7 +356,7 @@ const std::string& cmGeneratorTarget::GetName() const
std::string cmGeneratorTarget::GetExportName() const
{
- cmProp exportName = this->GetProperty("EXPORT_NAME");
+ cmValue exportName = this->GetProperty("EXPORT_NAME");
if (cmNonempty(exportName)) {
if (!cmGeneratorExpression::IsValidTargetName(*exportName)) {
@@ -381,9 +371,9 @@ std::string cmGeneratorTarget::GetExportName() const
return this->GetName();
}
-cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const
+cmValue cmGeneratorTarget::GetProperty(const std::string& prop) const
{
- if (cmProp result = cmTargetPropertyComputer::GetProperty(
+ if (cmValue result = cmTargetPropertyComputer::GetProperty(
this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
return result;
}
@@ -396,13 +386,7 @@ cmProp cmGeneratorTarget::GetProperty(const std::string& prop) const
std::string const& cmGeneratorTarget::GetSafeProperty(
std::string const& prop) const
{
- cmProp ret = this->GetProperty(prop);
- if (ret) {
- return *ret;
- }
-
- static std::string const s_empty;
- return s_empty;
+ return this->GetProperty(prop);
}
const char* cmGeneratorTarget::GetOutputTargetType(
@@ -491,7 +475,7 @@ std::string cmGeneratorTarget::GetOutputName(
std::string outName;
for (std::string const& p : props) {
- if (cmProp outNameProp = this->GetProperty(p)) {
+ if (cmValue outNameProp = this->GetProperty(p)) {
outName = *outNameProp;
break;
}
@@ -519,7 +503,7 @@ std::string cmGeneratorTarget::GetFilePrefix(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
- cmProp prefix = this->GetFilePrefixInternal(config, artifact);
+ cmValue prefix = this->GetFilePrefixInternal(config, artifact);
return prefix ? *prefix : std::string();
}
@@ -533,7 +517,7 @@ std::string cmGeneratorTarget::GetFileSuffix(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
- cmProp suffix = this->GetFileSuffixInternal(config, artifact);
+ cmValue suffix = this->GetFileSuffixInternal(config, artifact);
return suffix ? *suffix : std::string();
}
@@ -546,7 +530,7 @@ std::string cmGeneratorTarget::GetFileSuffix(
std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
{
- cmProp postfix = nullptr;
+ cmValue postfix = nullptr;
std::string frameworkPostfix;
if (!config.empty()) {
std::string configProp =
@@ -564,7 +548,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
// framework postfix.
frameworkPostfix = this->GetFrameworkMultiConfigPostfix(config);
if (!frameworkPostfix.empty()) {
- postfix = &frameworkPostfix;
+ postfix = cmValue(frameworkPostfix);
}
}
return postfix ? *postfix : std::string();
@@ -573,7 +557,7 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix(
const std::string& config) const
{
- cmProp postfix = nullptr;
+ cmValue postfix = nullptr;
if (!config.empty()) {
std::string configProp = cmStrCat("FRAMEWORK_MULTI_CONFIG_POSTFIX_",
cmSystemTools::UpperCase(config));
@@ -588,7 +572,7 @@ std::string cmGeneratorTarget::GetFrameworkMultiConfigPostfix(
return postfix ? *postfix : std::string();
}
-cmProp cmGeneratorTarget::GetFilePrefixInternal(
+cmValue cmGeneratorTarget::GetFilePrefixInternal(
std::string const& config, cmStateEnums::ArtifactType artifact,
const std::string& language) const
{
@@ -618,7 +602,7 @@ cmProp cmGeneratorTarget::GetFilePrefixInternal(
}
// Compute prefix value.
- cmProp targetPrefix =
+ cmValue targetPrefix =
(isImportedLibraryArtifact ? this->GetProperty("IMPORT_PREFIX")
: this->GetProperty("PREFIX"));
@@ -639,7 +623,7 @@ cmProp cmGeneratorTarget::GetFilePrefixInternal(
return targetPrefix;
}
-cmProp cmGeneratorTarget::GetFileSuffixInternal(
+cmValue cmGeneratorTarget::GetFileSuffixInternal(
std::string const& config, cmStateEnums::ArtifactType artifact,
const std::string& language) const
{
@@ -669,7 +653,7 @@ cmProp cmGeneratorTarget::GetFileSuffixInternal(
}
// Compute suffix value.
- cmProp targetSuffix =
+ cmValue targetSuffix =
(isImportedLibraryArtifact ? this->GetProperty("IMPORT_SUFFIX")
: this->GetProperty("SUFFIX"));
@@ -704,7 +688,8 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before)
{
this->SourceEntries.insert(
before ? this->SourceEntries.begin() : this->SourceEntries.end(),
- CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
+ CreateTargetPropertyEntry(
+ BT<std::string>(src, this->Makefile->GetBacktrace()), true));
this->ClearSourcesCache();
}
@@ -725,11 +710,13 @@ void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs)
void cmGeneratorTarget::AddIncludeDirectory(const std::string& src,
bool before)
{
- this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before);
+ this->Target->InsertInclude(
+ BT<std::string>(src, this->Makefile->GetBacktrace()), before);
this->IncludeDirectoriesEntries.insert(
before ? this->IncludeDirectoriesEntries.begin()
: this->IncludeDirectoriesEntries.end(),
- CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true));
+ CreateTargetPropertyEntry(
+ BT<std::string>(src, this->Makefile->GetBacktrace()), true));
}
std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(
@@ -751,7 +738,7 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
std::vector<std::string>& result,
bool excludeImported, std::string const& language)
{
- if (cmProp dirs =
+ if (cmValue dirs =
depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget,
dagChecker, depTgt, language),
@@ -761,7 +748,7 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
return;
}
- if (cmProp dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
+ if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
cmExpandList(cmGeneratorExpression::Evaluate(*dirs, lg, config, headTarget,
dagChecker, depTgt, language),
result);
@@ -813,17 +800,17 @@ void cmGeneratorTarget::ComputeObjectMapping()
}
}
-cmProp cmGeneratorTarget::GetFeature(const std::string& feature,
- const std::string& config) const
+cmValue cmGeneratorTarget::GetFeature(const std::string& feature,
+ const std::string& config) const
{
if (!config.empty()) {
std::string featureConfig =
cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
- if (cmProp value = this->GetProperty(featureConfig)) {
+ if (cmValue value = this->GetProperty(featureConfig)) {
return value;
}
}
- if (cmProp value = this->GetProperty(feature)) {
+ if (cmValue value = this->GetProperty(feature)) {
return value;
}
return this->LocalGenerator->GetFeature(feature, config);
@@ -851,7 +838,7 @@ const char* cmGeneratorTarget::GetLinkPIEProperty(
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
std::string const& config) const
{
- cmProp feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config);
+ cmValue feature = this->GetFeature("INTERPROCEDURAL_OPTIMIZATION", config);
if (!cmIsOn(feature)) {
// 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies
@@ -959,23 +946,23 @@ BTs<std::string> const* cmGeneratorTarget::GetLanguageStandardProperty(
cmStrCat(lang, "_STANDARD"));
}
-cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
- std::string const& config) const
+cmValue cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
+ std::string const& config) const
{
BTs<std::string> const* languageStandard =
this->GetLanguageStandardProperty(lang, config);
if (languageStandard) {
- return &(languageStandard->Value);
+ return cmValue(languageStandard->Value);
}
return nullptr;
}
-cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport(
+cmValue cmGeneratorTarget::GetPropertyWithPairedLanguageSupport(
std::string const& lang, const char* suffix) const
{
- cmProp propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
+ cmValue propertyValue = this->Target->GetProperty(cmStrCat(lang, suffix));
if (!propertyValue) {
// Check if we should use the value set by another language.
if (lang == "OBJC") {
@@ -988,7 +975,7 @@ cmProp cmGeneratorTarget::GetPropertyWithPairedLanguageSupport(
return propertyValue;
}
-cmProp cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
+cmValue cmGeneratorTarget::GetLanguageExtensions(std::string const& lang) const
{
return this->GetPropertyWithPairedLanguageSupport(lang, "_EXTENSIONS");
}
@@ -1150,6 +1137,7 @@ bool cmGeneratorTarget::IsInBuildSystem() const
if (!this->SourceEntries.empty()) {
return true;
}
+ break;
case cmStateEnums::UNKNOWN_LIBRARY:
break;
}
@@ -1183,7 +1171,7 @@ const std::string& cmGeneratorTarget::GetLocationForBuild() const
// Now handle the deprecated build-time configuration location.
std::string const noConfig;
location = this->GetDirectory(noConfig);
- cmProp cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
+ cmValue cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
if (cfgid && (*cfgid != ".")) {
location += "/";
location += *cfgid;
@@ -1343,7 +1331,7 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
cmGeneratorTarget const* headTarget =
context->HeadTarget ? context->HeadTarget : this;
- if (cmProp p = this->GetProperty(prop)) {
+ if (cmValue p = this->GetProperty(prop)) {
result = cmGeneratorExpressionNode::EvaluateDependentExpression(
*p, context->LG, context, headTarget, &dagChecker, this);
}
@@ -1466,7 +1454,7 @@ void AddLangSpecificImplicitIncludeDirectories(
auto* lg = dependency->GetLocalGenerator();
EvaluatedTargetPropertyEntry entry{ library, library.Backtrace };
- if (cmProp val = dependency->GetProperty(propertyName)) {
+ if (cmValue val = dependency->GetProperty(propertyName)) {
entry.Values.emplace_back(*val);
} else {
if (mode == IncludeDirectoryFallBack::BINARY) {
@@ -1681,9 +1669,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
// for TARGET_OBJECTS instead for backwards compatibility with OLD
// behavior of CMP0024 and CMP0026 only.
- cmStringRange sourceEntries = this->Target->GetSourceEntries();
- for (std::string const& entry : sourceEntries) {
- std::vector<std::string> items = cmExpandedList(entry);
+ cmBTStringRange sourceEntries = this->Target->GetSourceEntries();
+ for (auto const& entry : sourceEntries) {
+ std::vector<std::string> items = cmExpandedList(entry.Value);
for (std::string const& item : items) {
if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") &&
item.back() == '>') {
@@ -1998,12 +1986,12 @@ std::string cmGeneratorTarget::GetCompilePDBName(
// Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(config);
std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
- cmProp config_name = this->GetProperty(configProp);
+ cmValue config_name = this->GetProperty(configProp);
if (cmNonempty(config_name)) {
return prefix + *config_name + ".pdb";
}
- cmProp name = this->GetProperty("COMPILE_PDB_NAME");
+ cmValue name = this->GetProperty("COMPILE_PDB_NAME");
if (cmNonempty(name)) {
return prefix + *name + ".pdb";
}
@@ -2142,34 +2130,29 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
return true;
}
-#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
// Enable if the rpath flag uses a separator and the target uses
// binaries we know how to edit.
std::string ll = this->GetLinkerLanguage(config);
if (!ll.empty()) {
std::string sepVar =
cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
- cmProp sep = this->Makefile->GetDefinition(sepVar);
+ cmValue sep = this->Makefile->GetDefinition(sepVar);
if (cmNonempty(sep)) {
// TODO: Add binary format check to ABI detection and get rid of
// CMAKE_EXECUTABLE_FORMAT.
- if (cmProp fmt =
+ if (cmValue fmt =
this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) {
-# if defined(CMake_USE_ELF_PARSER)
if (*fmt == "ELF") {
return true;
}
-# endif
-# if defined(CMake_USE_XCOFF_PARSER)
+#if defined(CMake_USE_XCOFF_PARSER)
if (*fmt == "XCOFF") {
return true;
}
-# endif
+#endif
}
}
}
-#endif
- static_cast<void>(config);
return false;
}
@@ -2188,6 +2171,21 @@ bool cmGeneratorTarget::IsImportedSharedLibWithoutSOName(
bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
const std::string& config) const
{
+ TargetPtrToBoolMap& cache = this->MacOSXRpathInstallNameDirCache[config];
+ const auto lookup = cache.find(this->Target);
+
+ if (lookup != cache.cend()) {
+ return lookup->second;
+ }
+
+ const bool result = this->DetermineHasMacOSXRpathInstallNameDir(config);
+ cache[this->Target] = result;
+ return result;
+}
+
+bool cmGeneratorTarget::DetermineHasMacOSXRpathInstallNameDir(
+ const std::string& config) const
+{
bool install_name_is_rpath = false;
bool macosx_rpath = false;
@@ -2195,7 +2193,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
if (this->GetType() != cmStateEnums::SHARED_LIBRARY) {
return false;
}
- cmProp install_name = this->GetProperty("INSTALL_NAME_DIR");
+ cmValue install_name = this->GetProperty("INSTALL_NAME_DIR");
bool use_install_name = this->MacOSXUseInstallNameDir();
if (install_name && use_install_name && *install_name == "@rpath") {
install_name_is_rpath = true;
@@ -2253,7 +2251,7 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
return false;
}
- cmProp macosx_rpath_str = this->GetProperty("MACOSX_RPATH");
+ cmValue macosx_rpath_str = this->GetProperty("MACOSX_RPATH");
if (macosx_rpath_str) {
return this->GetPropertyAsBool("MACOSX_RPATH");
}
@@ -2270,7 +2268,7 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const
bool cmGeneratorTarget::MacOSXUseInstallNameDir() const
{
- cmProp build_with_install_name =
+ cmValue build_with_install_name =
this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR");
if (build_with_install_name) {
return cmIsOn(*build_with_install_name);
@@ -2363,7 +2361,7 @@ std::string cmGeneratorTarget::GetAppBundleDirectory(
{
std::string fpath = cmStrCat(
this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
- cmProp ext = this->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = this->GetProperty("BUNDLE_EXTENSION");
fpath += (ext ? *ext : "app");
if (shouldAddContentLevel(level) &&
!this->Makefile->PlatformIsAppleEmbedded()) {
@@ -2393,7 +2391,7 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(
std::string fpath = cmStrCat(
this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
std::string ext;
- if (cmProp p = this->GetProperty("BUNDLE_EXTENSION")) {
+ if (cmValue p = this->GetProperty("BUNDLE_EXTENSION")) {
ext = *p;
} else {
if (this->IsXCTestOnApple()) {
@@ -2418,7 +2416,7 @@ std::string cmGeneratorTarget::GetFrameworkDirectory(
{
std::string fpath = cmStrCat(
this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
- cmProp ext = this->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = this->GetProperty("BUNDLE_EXTENSION");
fpath += (ext ? *ext : "framework");
if (shouldAddFullLevel(level) &&
!this->Makefile->PlatformIsAppleEmbedded()) {
@@ -2470,7 +2468,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree(
{
if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
std::string dir;
- cmProp install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
+ cmValue install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
if (cmNonempty(install_name_dir)) {
@@ -2519,7 +2517,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->IsExecutableWithExports()) {
- if (cmProp custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
+ if (cmValue custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
this->ExportMacro = *custom_export_name;
} else {
std::string in = cmStrCat(this->GetName(), "_EXPORTS");
@@ -2561,6 +2559,7 @@ public:
} break;
case cmPolicies::OLD:
noMessage = true;
+ break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
@@ -2817,7 +2816,7 @@ std::string cmGeneratorTarget::GetEffectiveFolderName() const
return effectiveFolder;
}
- cmProp targetFolder = this->GetProperty("FOLDER");
+ cmValue targetFolder = this->GetProperty("FOLDER");
if (targetFolder) {
effectiveFolder += *targetFolder;
}
@@ -3045,7 +3044,7 @@ void cmTargetTraceDependencies::Trace()
this->CurrentEntry = &this->GeneratorTarget->SourceDepends[sf];
// Queue dependencies added explicitly by the user.
- if (cmProp additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) {
+ if (cmValue additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> objDeps = cmExpandedList(*additionalDeps);
for (std::string& objDep : objDeps) {
if (cmSystemTools::FileIsFullPath(objDep)) {
@@ -3243,7 +3242,7 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
if (!this->Makefile->IsOn("APPLE")) {
return;
}
- cmProp archs = nullptr;
+ cmValue archs = nullptr;
if (!config.empty()) {
std::string defVarName =
cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config));
@@ -3263,13 +3262,14 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
cmSourceFile const& sf) const
{
- cmProp lang = sf.GetProperty("LANGUAGE");
+ cmValue lang = sf.GetProperty("LANGUAGE");
if (!lang) {
return;
}
switch (this->GetPolicyStatusCMP0119()) {
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// The OLD behavior is to not add explicit language flags.
return;
@@ -3568,6 +3568,7 @@ void processIncludeDirectories(cmGeneratorTarget const* tgt,
} break;
case cmPolicies::OLD:
noMessage = true;
+ break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
@@ -3644,7 +3645,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
// If this target has ISPC sources make sure to add the header
// directory to other compilation units
if (cm::contains(this->GetAllConfigCompileLanguages(), "ISPC")) {
- if (cmProp val = this->GetProperty(propertyName)) {
+ if (cmValue val = this->GetProperty(propertyName)) {
includes.emplace_back(*val);
} else {
includes.emplace_back(this->GetObjectDirectory(config));
@@ -3974,7 +3975,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
if (!config.empty()) {
std::string configPropName =
"COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- cmProp configProp = this->GetProperty(configPropName);
+ cmValue configProp = this->GetProperty(configPropName);
if (configProp) {
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) {
case cmPolicies::WARN: {
@@ -4049,7 +4050,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
return std::string();
}
const cmGeneratorTarget* generatorTarget = this;
- cmProp pchReuseFrom =
+ cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
const auto inserted =
@@ -4090,8 +4091,10 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
const std::string filename_tmp = cmStrCat(filename, ".tmp");
if (!pchReuseFrom) {
- cmProp pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
- cmProp pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
+ cmValue pchPrologue =
+ this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
+ cmValue pchEpilogue =
+ this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
std::string firstHeaderOnDisk;
{
@@ -4105,7 +4108,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
if (this->GetGlobalGenerator()->IsXcode()) {
file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
}
- if (language == "CXX") {
+ if (language == "CXX" && !this->GetGlobalGenerator()->IsXcode()) {
file << "#ifdef __cplusplus\n";
}
for (auto const& header_bt : headers) {
@@ -4123,7 +4126,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
firstHeaderOnDisk = header_bt.Value;
}
}
- if (language == "CXX") {
+ if (language == "CXX" && !this->GetGlobalGenerator()->IsXcode()) {
file << "#endif // __cplusplus\n";
}
if (this->GetGlobalGenerator()->IsXcode()) {
@@ -4162,7 +4165,7 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
std::string& filename = inserted.first->second;
const cmGeneratorTarget* generatorTarget = this;
- cmProp pchReuseFrom =
+ cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (pchReuseFrom) {
generatorTarget =
@@ -4260,7 +4263,7 @@ std::string cmGeneratorTarget::GetPchFile(const std::string& config,
};
cmGeneratorTarget* generatorTarget = this;
- cmProp pchReuseFrom =
+ cmValue pchReuseFrom =
generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
if (pchReuseFrom) {
generatorTarget =
@@ -4466,6 +4469,13 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
// Last step: replace "LINKER:" prefixed elements by
// actual linker wrapper
+ return this->ResolveLinkerWrapper(result, language);
+}
+
+std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper(
+ std::vector<BT<std::string>>& result, const std::string& language) const
+{
+ // replace "LINKER:" prefixed elements by actual linker wrapper
const std::string wrapper(this->Makefile->GetSafeDefinition(
"CMAKE_" + language +
(this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG"
@@ -4549,7 +4559,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
nullptr, nullptr);
EvaluatedTargetPropertyEntries entries;
- if (cmProp linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
+ if (cmValue linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
std::vector<std::string> options = cmExpandedList(*linkOptions);
for (const auto& option : options) {
std::unique_ptr<TargetPropertyEntry> entry =
@@ -4700,7 +4710,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
nullptr);
EvaluatedTargetPropertyEntries entries;
- if (cmProp linkDepends = this->GetProperty("LINK_DEPENDS")) {
+ if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) {
std::vector<std::string> depends = cmExpandedList(*linkDepends);
for (const auto& depend : depends) {
std::unique_ptr<TargetPropertyEntry> entry =
@@ -4781,7 +4791,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(std::string const& config) const
}
std::string key = cmStrCat(cmSystemTools::UpperCase(config), '-', lang);
- cmProp currentLanguageStandard = this->GetLanguageStandard(lang, config);
+ cmValue currentLanguageStandard = this->GetLanguageStandard(lang, config);
std::string newRequiredStandard;
if (!standardResolver.GetNewRequiredStandard(
@@ -4821,7 +4831,7 @@ bool cmGeneratorTarget::ComputeCompileFeatures(
this->LanguageStandardMap[key] = *standardToCopy;
generatorTargetLanguageStandard = &this->LanguageStandardMap[key];
} else {
- cmProp defaultStandard = this->Makefile->GetDefinition(
+ cmValue defaultStandard = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", language.second, "_STANDARD_DEFAULT"));
if (defaultStandard) {
this->LanguageStandardMap[key] = BTs<std::string>(*defaultStandard);
@@ -4924,8 +4934,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
}
// Check for library version properties.
- cmProp version = this->GetProperty("VERSION");
- cmProp soversion = this->GetProperty("SOVERSION");
+ cmValue version = this->GetProperty("VERSION");
+ cmValue soversion = this->GetProperty("SOVERSION");
if (!this->HasSOName(config) ||
this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") ||
this->IsFrameworkOnApple()) {
@@ -4966,11 +4976,11 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
// The library's soname.
this->ComputeVersionedName(targetNames.SharedObject, prefix,
targetNames.Base, suffix, targetNames.Output,
- cmToCStr(soversion));
+ soversion);
// The library's real name on disk.
this->ComputeVersionedName(targetNames.Real, prefix, targetNames.Base,
- suffix, targetNames.Output, cmToCStr(version));
+ suffix, targetNames.Output, version);
}
// The import library name.
@@ -5003,10 +5013,10 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
// This versioning is supported only for executables and then only
// when the platform supports symbolic links.
#if defined(_WIN32) && !defined(__CYGWIN__)
- const char* version = nullptr;
+ cmValue version;
#else
// Check for executable version properties.
- const char* version = cmToCStr(this->GetProperty("VERSION"));
+ cmValue version = this->GetProperty("VERSION");
if (this->GetType() != cmStateEnums::EXECUTABLE ||
this->Makefile->IsOn("XCODE")) {
version = nullptr;
@@ -5030,7 +5040,7 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
#endif
if (version) {
targetNames.Real += "-";
- targetNames.Real += version;
+ targetNames.Real += *version;
}
#if defined(__CYGWIN__)
targetNames.Real += suffix;
@@ -5100,8 +5110,8 @@ void cmGeneratorTarget::GetFullNameInternal(
// retrieve prefix and suffix
std::string ll = this->GetLinkerLanguage(config);
- cmProp targetPrefix = this->GetFilePrefixInternal(config, artifact, ll);
- cmProp targetSuffix = this->GetFileSuffixInternal(config, artifact, ll);
+ cmValue targetPrefix = this->GetFilePrefixInternal(config, artifact, ll);
+ cmValue targetSuffix = this->GetFileSuffixInternal(config, artifact, ll);
// The implib option is only allowed for shared libraries, module
// libraries, and executables.
@@ -5119,13 +5129,13 @@ void cmGeneratorTarget::GetFullNameInternal(
if (this->IsFrameworkOnApple()) {
fw_prefix =
cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmValue(fw_prefix);
targetSuffix = nullptr;
}
if (this->IsCFBundleOnApple()) {
fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmValue(fw_prefix);
targetSuffix = nullptr;
}
@@ -5141,13 +5151,13 @@ void cmGeneratorTarget::GetFullNameInternal(
// EXECUTABLE_SUFFIX attribute.
if (this->IsFrameworkOnApple() &&
this->GetGlobalGenerator()->GetName() == "Xcode") {
- targetSuffix = &configPostfix;
+ targetSuffix = cmValue(configPostfix);
} else {
outBase += configPostfix;
}
// Name shared libraries with their version number on some platforms.
- if (cmProp soversion = this->GetProperty("SOVERSION")) {
+ if (cmValue soversion = this->GetProperty("SOVERSION")) {
if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
!isImportedLibraryArtifact &&
this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) {
@@ -5183,7 +5193,7 @@ std::string cmGeneratorTarget::GetPDBOutputName(
props.emplace_back("PDB_NAME");
for (std::string const& p : props) {
- if (cmProp outName = this->GetProperty(p)) {
+ if (cmValue outName = this->GetProperty(p)) {
base = *outName;
break;
}
@@ -5210,7 +5220,7 @@ std::string cmGeneratorTarget::GetPDBName(const std::string& config) const
props.emplace_back("PDB_NAME");
for (std::string const& p : props) {
- if (cmProp outName = this->GetProperty(p)) {
+ if (cmValue outName = this->GetProperty(p)) {
base = *outName;
break;
}
@@ -5293,7 +5303,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
} else {
// Handle the MACOSX_PACKAGE_LOCATION property on source files that
// were not listed in one of the other lists.
- if (cmProp location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
+ if (cmValue location = sf->GetProperty("MACOSX_PACKAGE_LOCATION")) {
flags.MacFolder = location->c_str();
const bool stripResources =
this->GlobalGenerator->ShouldStripResourcePath(this->Makefile);
@@ -5323,7 +5333,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
this->SourceFileFlagsConstructed = true;
// Process public headers to mark the source files.
- if (cmProp files = this->GetProperty("PUBLIC_HEADER")) {
+ if (cmValue files = this->GetProperty("PUBLIC_HEADER")) {
std::vector<std::string> relFiles = cmExpandedList(*files);
for (std::string const& relFile : relFiles) {
if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
@@ -5336,7 +5346,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
// Process private headers after public headers so that they take
// precedence if a file is listed in both.
- if (cmProp files = this->GetProperty("PRIVATE_HEADER")) {
+ if (cmValue files = this->GetProperty("PRIVATE_HEADER")) {
std::vector<std::string> relFiles = cmExpandedList(*files);
for (std::string const& relFile : relFiles) {
if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
@@ -5348,7 +5358,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const
}
// Mark sources listed as resources.
- if (cmProp files = this->GetProperty("RESOURCE")) {
+ if (cmValue files = this->GetProperty("RESOURCE")) {
std::vector<std::string> relFiles = cmExpandedList(*files);
for (std::string const& relFile : relFiles) {
if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) {
@@ -5376,7 +5386,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
this->GetLinkImplementationClosure(config);
for (cmGeneratorTarget const* li : deps) {
#define CM_READ_COMPATIBLE_INTERFACE(X, x) \
- if (cmProp prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
+ if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
std::vector<std::string> props; \
cmExpandList(*prop, props); \
compat.Props##x.insert(props.begin(), props.end()); \
@@ -5486,7 +5496,7 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
const std::string& config, CompatibleType t,
PropertyType* /*unused*/)
{
- cmProp prop = dependee->GetProperty(propName);
+ cmValue prop = dependee->GetProperty(propName);
if (!prop) {
return;
}
@@ -5672,6 +5682,11 @@ std::string valueAsString<std::string>(std::string value)
return value;
}
template <>
+std::string valueAsString<cmValue>(cmValue value)
+{
+ return value ? value : std::string("(unset)");
+}
+template <>
std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
{
return "(unset)";
@@ -5721,7 +5736,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
return tgt->GetPropertyAsBool(prop);
}
- cmProp value = tgt->GetProperty(prop);
+ cmValue value = tgt->GetProperty(prop);
return cmIsOn(genexInterpreter->Evaluate(value ? *value : "", prop));
}
@@ -5730,10 +5745,10 @@ const char* getTypedProperty<const char*>(
cmGeneratorTarget const* tgt, const std::string& prop,
cmGeneratorExpressionInterpreter* genexInterpreter)
{
- cmProp value = tgt->GetProperty(prop);
+ cmValue value = tgt->GetProperty(prop);
if (genexInterpreter == nullptr) {
- return cmToCStr(value);
+ return value.GetCStr();
}
return genexInterpreter->Evaluate(value ? *value : "", prop).c_str();
@@ -5744,10 +5759,10 @@ std::string getTypedProperty<std::string>(
cmGeneratorTarget const* tgt, const std::string& prop,
cmGeneratorExpressionInterpreter* genexInterpreter)
{
- cmProp value = tgt->GetProperty(prop);
+ cmValue value = tgt->GetProperty(prop);
if (genexInterpreter == nullptr) {
- return valueAsString(cmToCStr(value));
+ return valueAsString(value);
}
return genexInterpreter->Evaluate(value ? *value : "", prop);
@@ -6121,7 +6136,7 @@ void cmGeneratorTarget::GetTargetVersion(const std::string& property,
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
- if (cmProp version = this->GetProperty(property)) {
+ if (cmValue version = this->GetProperty(property)) {
// Try to parse the version number and store the results that were
// successfully parsed.
int parsed_major;
@@ -6149,12 +6164,12 @@ std::string cmGeneratorTarget::GetRuntimeLinkLibrary(
{
// This is activated by the presence of a default selection whether or
// not it is overridden by a property.
- cmProp runtimeLibraryDefault = this->Makefile->GetDefinition(
+ cmValue runtimeLibraryDefault = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT"));
if (!cmNonempty(runtimeLibraryDefault)) {
return std::string();
}
- cmProp runtimeLibraryValue =
+ cmValue runtimeLibraryValue =
this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY"));
if (!runtimeLibraryValue) {
runtimeLibraryValue = runtimeLibraryDefault;
@@ -6175,12 +6190,21 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory(
return this->FortranModuleDirectory;
}
+bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const
+{
+ if (cmValue prop =
+ this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) {
+ return cmIsOn(*prop);
+ }
+ return false;
+}
+
std::string cmGeneratorTarget::CreateFortranModuleDirectory(
std::string const& working_dir) const
{
std::string mod_dir;
std::string target_mod_dir;
- if (cmProp prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) {
+ if (cmValue prop = this->GetProperty("Fortran_MODULE_DIRECTORY")) {
target_mod_dir = *prop;
} else {
std::string const& default_mod_dir =
@@ -6189,7 +6213,7 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory(
target_mod_dir = default_mod_dir;
}
}
- cmProp moddir_flag =
+ cmValue moddir_flag =
this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
if (!target_mod_dir.empty() && moddir_flag) {
// Compute the full path to the module directory.
@@ -6272,26 +6296,23 @@ std::string cmGeneratorTarget::GetFrameworkVersion() const
{
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
- if (cmProp fversion = this->GetProperty("FRAMEWORK_VERSION")) {
+ if (cmValue fversion = this->GetProperty("FRAMEWORK_VERSION")) {
return *fversion;
}
- if (cmProp tversion = this->GetProperty("VERSION")) {
+ if (cmValue tversion = this->GetProperty("VERSION")) {
return *tversion;
}
return "A";
}
-void cmGeneratorTarget::ComputeVersionedName(std::string& vName,
- std::string const& prefix,
- std::string const& base,
- std::string const& suffix,
- std::string const& name,
- const char* version) const
+void cmGeneratorTarget::ComputeVersionedName(
+ std::string& vName, std::string const& prefix, std::string const& base,
+ std::string const& suffix, std::string const& name, cmValue version) const
{
vName = this->Makefile->IsOn("APPLE") ? (prefix + base) : name;
if (version) {
vName += ".";
- vName += version;
+ vName += *version;
}
vName += this->Makefile->IsOn("APPLE") ? suffix : std::string();
}
@@ -6358,16 +6379,16 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
if (name == this->GetName() || name.empty()) {
return maybeItem;
}
- maybeItem = this->ResolveLinkItem(name, bt, scope->LG);
+ maybeItem = this->ResolveLinkItem(BT<std::string>(name, bt), scope->LG);
return maybeItem;
}
-void cmGeneratorTarget::ExpandLinkItems(
- std::string const& prop, std::string const& value, std::string const& config,
- cmGeneratorTarget const* headTarget, bool usage_requirements_only,
- std::vector<cmLinkItem>& items, std::vector<cmLinkItem>& objects,
- bool& hadHeadSensitiveCondition, bool& hadContextSensitiveCondition,
- bool& hadLinkLanguageSensitiveCondition) const
+void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
+ std::string const& value,
+ std::string const& config,
+ cmGeneratorTarget const* headTarget,
+ bool usage_requirements_only,
+ cmLinkInterface& iface) const
{
// Keep this logic in sync with ComputeLinkImplementationLibraries.
cmGeneratorExpression ge;
@@ -6389,24 +6410,27 @@ void cmGeneratorTarget::ExpandLinkItems(
for (std::string const& lib : libs) {
if (cm::optional<cmLinkItem> maybeItem =
this->LookupLinkItem(lib, cge->GetBacktrace(), &scope)) {
- if (!maybeItem->Target) {
+ cmLinkItem item = std::move(*maybeItem);
+
+ if (!item.Target) {
// Report explicitly linked object files separately.
- std::string const& maybeObj = maybeItem->AsStr();
+ std::string const& maybeObj = item.AsStr();
if (cmSystemTools::FileIsFullPath(maybeObj)) {
cmSourceFile const* sf =
mf->GetSource(maybeObj, cmSourceFileLocationKind::Known);
if (sf && sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
- objects.emplace_back(std::move(*maybeItem));
+ iface.Objects.emplace_back(std::move(item));
continue;
}
}
}
- items.emplace_back(std::move(*maybeItem));
+
+ iface.Libraries.emplace_back(std::move(item));
}
}
- hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
- hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
- hadLinkLanguageSensitiveCondition =
+ iface.HadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
+ iface.HadContextSensitiveCondition = cge->GetHadContextSensitiveCondition();
+ iface.HadLinkLanguageSensitiveCondition =
cge->GetHadLinkLanguageSensitiveCondition();
}
@@ -6531,9 +6555,9 @@ void cmGeneratorTarget::ComputeLinkInterface(
// How many repetitions are needed if this library has cyclic
// dependencies?
std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
- if (cmProp config_reps = this->GetProperty(propName)) {
+ if (cmValue config_reps = this->GetProperty(propName)) {
sscanf(config_reps->c_str(), "%u", &iface.Multiplicity);
- } else if (cmProp reps =
+ } else if (cmValue reps =
this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) {
sscanf(reps->c_str(), "%u", &iface.Multiplicity);
}
@@ -6690,14 +6714,14 @@ bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
}
// Select an output directory.
- if (cmProp config_outdir = this->GetProperty(configProp)) {
+ if (cmValue config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator,
config, this);
// Skip per-configuration subdirectory.
conf.clear();
- } else if (cmProp outdir = this->GetProperty(propertyName)) {
+ } else if (cmValue outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
out = cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator,
config, this);
@@ -6760,14 +6784,14 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
}
// Select an output directory.
- if (cmProp config_outdir = this->GetProperty(configProp)) {
+ if (cmValue config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
out = cmGeneratorExpression::Evaluate(*config_outdir, this->LocalGenerator,
config);
// Skip per-configuration subdirectory.
conf.clear();
- } else if (cmProp outdir = this->GetProperty(propertyName)) {
+ } else if (cmValue outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
out =
cmGeneratorExpression::Evaluate(*outdir, this->LocalGenerator, config);
@@ -6820,7 +6844,7 @@ bool cmGeneratorTarget::GetRPATH(const std::string& config,
const std::string& prop,
std::string& rpath) const
{
- cmProp value = this->GetProperty(prop);
+ cmValue value = this->GetProperty(prop);
if (!value) {
return false;
}
@@ -6845,7 +6869,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
- cmProp explicitLibraries = nullptr;
+ cmValue explicitLibraries = nullptr;
std::string linkIfaceProp;
bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD &&
this->GetPolicyStatusCMP0022() != cmPolicies::WARN);
@@ -6874,7 +6898,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
!this->PolicyWarnedCMP0022) {
// Compare the explicitly set old link interface properties to the
// preferred new link interface property one and warn if different.
- cmProp newExplicitLibraries =
+ cmValue newExplicitLibraries =
this->GetProperty("INTERFACE_LINK_LIBRARIES");
if (newExplicitLibraries &&
(*newExplicitLibraries != *explicitLibraries)) {
@@ -6903,23 +6927,20 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
return;
}
iface.Exists = true;
+
+ // If CMP0022 is NEW then the plain tll signature sets the
+ // INTERFACE_LINK_LIBRARIES property. Even if the project
+ // clears it, the link interface is still explicit.
iface.Explicit = cmp0022NEW || explicitLibraries;
if (explicitLibraries) {
// The interface libraries have been explicitly set.
this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config,
- headTarget, usage_requirements_only, iface.Libraries,
- iface.Objects, iface.HadHeadSensitiveCondition,
- iface.HadContextSensitiveCondition,
- iface.HadLinkLanguageSensitiveCondition);
- return;
+ headTarget, usage_requirements_only, iface);
}
- // If CMP0022 is NEW then the plain tll signature sets the
- // INTERFACE_LINK_LIBRARIES, so if we get here then the project
- // cleared the property explicitly and we should not fall back
- // to the link implementation.
- if (cmp0022NEW) {
+ // If the link interface is explicit, do not fall back to the link impl.
+ if (iface.Explicit) {
return;
}
@@ -6932,22 +6953,15 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
!this->PolicyWarnedCMP0022 && !usage_requirements_only) {
// Compare the link implementation fallback link interface to the
// preferred new link interface property and warn if different.
- std::vector<cmLinkItem> ifaceLibs;
- std::vector<cmLinkItem> ifaceObjects;
+ cmLinkInterface ifaceNew;
static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
- if (cmProp newExplicitLibraries = this->GetProperty(newProp)) {
- bool hadHeadSensitiveConditionDummy = false;
- bool hadContextSensitiveConditionDummy = false;
- bool hadLinkLanguageSensitiveConditionDummy = false;
+ if (cmValue newExplicitLibraries = this->GetProperty(newProp)) {
this->ExpandLinkItems(newProp, *newExplicitLibraries, config,
- headTarget, usage_requirements_only, ifaceLibs,
- ifaceObjects, hadHeadSensitiveConditionDummy,
- hadContextSensitiveConditionDummy,
- hadLinkLanguageSensitiveConditionDummy);
+ headTarget, usage_requirements_only, ifaceNew);
}
- if (ifaceLibs != iface.Libraries) {
+ if (ifaceNew.Libraries != iface.Libraries) {
std::string oldLibraries = cmJoin(impl->Libraries, ";");
- std::string newLibraries = cmJoin(ifaceLibs, ";");
+ std::string newLibraries = cmJoin(ifaceNew.Libraries, ";");
if (oldLibraries.empty()) {
oldLibraries = "(empty)";
}
@@ -7009,7 +7023,7 @@ std::vector<ValueType> computeImplicitLanguageTargets(
std::string const& runtimeLibrary =
currentTarget->GetRuntimeLinkLibrary(lang, config);
- if (cmProp runtimeLinkOptions = currentTarget->Makefile->GetDefinition(
+ if (cmValue runtimeLinkOptions = currentTarget->Makefile->GetDefinition(
"CMAKE_" + lang + "_RUNTIME_LIBRARIES_" + runtimeLibrary)) {
std::vector<std::string> libsVec = cmExpandedList(*runtimeLinkOptions);
result.reserve(libsVec.size());
@@ -7085,10 +7099,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
iface.Multiplicity = info->Multiplicity;
cmExpandList(info->Languages, iface.Languages);
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
- headTarget, usage_requirements_only, iface.Libraries,
- iface.Objects, iface.HadHeadSensitiveCondition,
- iface.HadContextSensitiveCondition,
- iface.HadLinkLanguageSensitiveCondition);
+ headTarget, usage_requirements_only, iface);
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
LookupLinkItemScope scope{ this->LocalGenerator };
for (std::string const& dep : deps) {
@@ -7150,8 +7161,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Initialize members.
info.NoSOName = false;
- cmProp loc = nullptr;
- cmProp imp = nullptr;
+ cmValue loc = nullptr;
+ cmValue imp = nullptr;
std::string suffix;
if (!this->Target->GetMappedConfig(desired_config, loc, imp, suffix)) {
return;
@@ -7160,7 +7171,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link interface.
{
std::string linkProp = "INTERFACE_LINK_LIBRARIES";
- cmProp propertyLibs = this->GetProperty(linkProp);
+ cmValue propertyLibs = this->GetProperty(linkProp);
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
if (!propertyLibs) {
@@ -7193,9 +7204,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
info.Location = *loc;
} else {
std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
- if (cmProp config_location = this->GetProperty(impProp)) {
+ if (cmValue config_location = this->GetProperty(impProp)) {
info.Location = *config_location;
- } else if (cmProp location = this->GetProperty("IMPORTED_LOCATION")) {
+ } else if (cmValue location = this->GetProperty("IMPORTED_LOCATION")) {
info.Location = *location;
}
}
@@ -7203,9 +7214,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the soname.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string soProp = cmStrCat("IMPORTED_SONAME", suffix);
- if (cmProp config_soname = this->GetProperty(soProp)) {
+ if (cmValue config_soname = this->GetProperty(soProp)) {
info.SOName = *config_soname;
- } else if (cmProp soname = this->GetProperty("IMPORTED_SONAME")) {
+ } else if (cmValue soname = this->GetProperty("IMPORTED_SONAME")) {
info.SOName = *soname;
}
}
@@ -7213,9 +7224,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get the "no-soname" mark.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix);
- if (cmProp config_no_soname = this->GetProperty(soProp)) {
+ if (cmValue config_no_soname = this->GetProperty(soProp)) {
info.NoSOName = cmIsOn(*config_no_soname);
- } else if (cmProp no_soname = this->GetProperty("IMPORTED_NO_SONAME")) {
+ } else if (cmValue no_soname = this->GetProperty("IMPORTED_NO_SONAME")) {
info.NoSOName = cmIsOn(*no_soname);
}
}
@@ -7226,9 +7237,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
} else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) {
std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
- if (cmProp config_implib = this->GetProperty(impProp)) {
+ if (cmValue config_implib = this->GetProperty(impProp)) {
info.ImportLibrary = *config_implib;
- } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) {
+ } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
info.ImportLibrary = *implib;
}
}
@@ -7237,9 +7248,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
{
std::string linkProp =
cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix);
- if (cmProp config_libs = this->GetProperty(linkProp)) {
+ if (cmValue config_libs = this->GetProperty(linkProp)) {
info.SharedDeps = *config_libs;
- } else if (cmProp libs =
+ } else if (cmValue libs =
this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES")) {
info.SharedDeps = *libs;
}
@@ -7249,9 +7260,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
if (this->LinkLanguagePropagatesToDependents()) {
std::string linkProp =
cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix);
- if (cmProp config_libs = this->GetProperty(linkProp)) {
+ if (cmValue config_libs = this->GetProperty(linkProp)) {
info.Languages = *config_libs;
- } else if (cmProp libs =
+ } else if (cmValue libs =
this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES")) {
info.Languages = *libs;
}
@@ -7260,9 +7271,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
// Get information if target is managed assembly.
{
std::string linkProp = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
- if (cmProp pc = this->GetProperty(linkProp + suffix)) {
+ if (cmValue pc = this->GetProperty(linkProp + suffix)) {
info.Managed = this->CheckManagedType(*pc);
- } else if (cmProp p = this->GetProperty(linkProp)) {
+ } else if (cmValue p = this->GetProperty(linkProp)) {
info.Managed = this->CheckManagedType(*p);
}
}
@@ -7271,9 +7282,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
std::string linkProp =
cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
- if (cmProp config_reps = this->GetProperty(linkProp)) {
+ if (cmValue config_reps = this->GetProperty(linkProp)) {
sscanf(config_reps->c_str(), "%u", &info.Multiplicity);
- } else if (cmProp reps =
+ } else if (cmValue reps =
this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) {
sscanf(reps->c_str(), "%u", &info.Multiplicity);
}
@@ -7381,9 +7392,9 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026(
// there is no cmGeneratorTarget at configure-time, so search the SOURCES
// for TARGET_OBJECTS instead for backwards compatibility with OLD
// behavior of CMP0024 and CMP0026 only.
- cmStringRange rng = this->Target->GetSourceEntries();
- for (std::string const& entry : rng) {
- std::vector<std::string> files = cmExpandedList(entry);
+ cmBTStringRange rng = this->Target->GetSourceEntries();
+ for (auto const& entry : rng) {
+ std::vector<std::string> files = cmExpandedList(entry.Value);
for (std::string const& li : files) {
if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') {
std::string objLibName = li.substr(17, li.size() - 18);
@@ -7426,6 +7437,7 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
cm->IssueMessage(MessageType::AUTHOR_WARNING, w.str(),
this->GetBacktrace());
}
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::NEW: {
@@ -7452,14 +7464,14 @@ std::string cmGeneratorTarget::CheckCMP0004(std::string const& item) const
bool cmGeneratorTarget::IsDeprecated() const
{
- cmProp deprecation = this->GetProperty("DEPRECATION");
+ cmValue deprecation = this->GetProperty("DEPRECATION");
return cmNonempty(deprecation);
}
std::string cmGeneratorTarget::GetDeprecation() const
{
// find DEPRECATION property
- if (cmProp deprecation = this->GetProperty("DEPRECATION")) {
+ if (cmValue deprecation = this->GetProperty("DEPRECATION")) {
return *deprecation;
}
return std::string();
@@ -7530,7 +7542,7 @@ bool cmGeneratorTarget::IsCSharpOnly() const
std::set<std::string> languages = this->GetAllConfigCompileLanguages();
// Consider an explicit linker language property, but *not* the
// computed linker language that may depend on linked targets.
- cmProp linkLang = this->GetProperty("LINKER_LANGUAGE");
+ cmValue linkLang = this->GetProperty("LINKER_LANGUAGE");
if (cmNonempty(linkLang)) {
languages.insert(*linkLang);
}
@@ -7611,23 +7623,21 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
{
cmLocalGenerator const* lg = this->LocalGenerator;
cmMakefile const* mf = lg->GetMakefile();
- cmStringRange entryRange = this->Target->GetLinkImplementationEntries();
- cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces();
- cmBacktraceRange::const_iterator btIt = btRange.begin();
+ cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries();
// Collect libraries directly linked in this configuration.
- for (cmStringRange::const_iterator le = entryRange.begin(),
- end = entryRange.end();
- le != end; ++le, ++btIt) {
+ for (auto const& entry : entryRange) {
std::vector<std::string> llibs;
// Keep this logic in sync with ExpandLinkItems.
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
nullptr);
- cmGeneratorExpression ge(*btIt);
- std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
+ cmGeneratorExpression ge(entry.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> const cge =
+ ge.Parse(entry.Value);
cge->SetEvaluateForBuildsystem(true);
std::string const& evaluated =
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
this->LinkerLanguage);
+ bool const fromGenex = evaluated != entry.Value;
cmExpandList(evaluated, llibs);
if (cge->GetHadHeadSensitiveCondition()) {
impl.HadHeadSensitiveCondition = true;
@@ -7665,6 +7675,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
} break;
case cmPolicies::OLD:
noMessage = true;
+ break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
@@ -7685,7 +7696,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
// The entry is meant for this configuration.
- cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg);
+ cmLinkItem item =
+ this->ResolveLinkItem(BT<std::string>(name, entry.Backtrace), lg);
if (!item.Target) {
// Report explicitly linked object files separately.
std::string const& maybeObj = item.AsStr();
@@ -7699,7 +7711,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
}
- impl.Libraries.emplace_back(std::move(item), evaluated != *le);
+ impl.Libraries.emplace_back(std::move(item), fromGenex);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
@@ -7727,7 +7739,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
// Support OLD behavior for CMP0003.
impl.WrongConfigLibraries.push_back(
- this->ResolveLinkItem(name, cmListFileBacktrace()));
+ this->ResolveLinkItem(BT<std::string>(name)));
}
}
}
@@ -7753,16 +7765,16 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference(
}
cmLinkItem cmGeneratorTarget::ResolveLinkItem(
- std::string const& name, cmListFileBacktrace const& bt) const
+ BT<std::string> const& name) const
{
- return this->ResolveLinkItem(name, bt, this->LocalGenerator);
+ return this->ResolveLinkItem(name, this->LocalGenerator);
}
-cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name,
- cmListFileBacktrace const& bt,
+cmLinkItem cmGeneratorTarget::ResolveLinkItem(BT<std::string> const& name,
cmLocalGenerator const* lg) const
{
- TargetOrString resolved = this->ResolveTargetReference(name, lg);
+ auto bt = name.Backtrace;
+ TargetOrString resolved = this->ResolveTargetReference(name.Value, lg);
if (!resolved.Target) {
return cmLinkItem(resolved.String, false, bt);
@@ -7940,7 +7952,7 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
}
// Check for explicitly set clr target property.
- if (cmProp clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
+ if (cmValue clr = this->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
return this->CheckManagedType(*clr);
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 6d2aa85ed..990696307 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -19,8 +19,8 @@
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
class cmComputeLinkInformation;
class cmCustomCommand;
@@ -89,7 +89,7 @@ public:
std::vector<std::string> GetPropertyKeys() const;
//! Might return a nullptr if the property is not set or invalid
- cmProp GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop) const;
//! Always returns a valid pointer
std::string const& GetSafeProperty(std::string const& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
@@ -163,10 +163,10 @@ public:
BTs<std::string> const* GetLanguageStandardProperty(
std::string const& lang, std::string const& config) const;
- cmProp GetLanguageStandard(std::string const& lang,
- std::string const& config) const;
+ cmValue GetLanguageStandard(std::string const& lang,
+ std::string const& config) const;
- cmProp GetLanguageExtensions(std::string const& lang) const;
+ cmValue GetLanguageExtensions(std::string const& lang) const;
bool GetLanguageStandardRequired(std::string const& lang) const;
@@ -187,8 +187,8 @@ public:
void ComputeObjectMapping();
- cmProp GetFeature(const std::string& feature,
- const std::string& config) const;
+ cmValue GetFeature(const std::string& feature,
+ const std::string& config) const;
const char* GetLinkPIEProperty(const std::string& config) const;
@@ -221,7 +221,7 @@ public:
{
this->PreviousState = target.SetDeviceLink(true);
}
- ~DeviceLinkSetter() { this->Target.SetDeviceLink(this->PreviousState); };
+ ~DeviceLinkSetter() { this->Target.SetDeviceLink(this->PreviousState); }
private:
cmGeneratorTarget& Target;
@@ -409,10 +409,8 @@ public:
TargetOrString ResolveTargetReference(std::string const& name,
cmLocalGenerator const* lg) const;
- cmLinkItem ResolveLinkItem(std::string const& name,
- cmListFileBacktrace const& bt) const;
- cmLinkItem ResolveLinkItem(std::string const& name,
- cmListFileBacktrace const& bt,
+ cmLinkItem ResolveLinkItem(BT<std::string> const& name) const;
+ cmLinkItem ResolveLinkItem(BT<std::string> const& name,
cmLocalGenerator const* lg) const;
// Compute the set of languages compiled by the target. This is
@@ -498,6 +496,9 @@ public:
std::vector<BT<std::string>> GetLinkOptions(
std::string const& config, std::string const& language) const;
+ std::vector<BT<std::string>>& ResolveLinkerWrapper(
+ std::vector<BT<std::string>>& result, const std::string& language) const;
+
void GetStaticLibraryLinkOptions(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
@@ -832,8 +833,9 @@ public:
std::string const& config) const;
std::string GetFortranModuleDirectory(std::string const& working_dir) const;
+ bool IsFortranBuildingInstrinsicModules() const;
- const std::string& GetSourcesProperty() const;
+ cmValue GetSourcesProperty() const;
void AddISPCGeneratedHeader(std::string const& header,
std::string const& config);
@@ -864,6 +866,11 @@ private:
mutable std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
+ using TargetPtrToBoolMap = std::unordered_map<cmTarget*, bool>;
+ mutable std::unordered_map<std::string, TargetPtrToBoolMap>
+ MacOSXRpathInstallNameDirCache;
+ bool DetermineHasMacOSXRpathInstallNameDir(const std::string& config) const;
+
// "config/language" is the key
mutable std::map<std::string, std::vector<std::string>> SystemIncludesCache;
@@ -877,12 +884,12 @@ private:
bool NeedImportLibraryName(std::string const& config) const;
- cmProp GetFilePrefixInternal(std::string const& config,
- cmStateEnums::ArtifactType artifact,
- const std::string& language = "") const;
- cmProp GetFileSuffixInternal(std::string const& config,
- cmStateEnums::ArtifactType artifact,
- const std::string& language = "") const;
+ cmValue GetFilePrefixInternal(std::string const& config,
+ cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
+ cmValue GetFileSuffixInternal(std::string const& config,
+ cmStateEnums::ArtifactType artifact,
+ const std::string& language = "") const;
std::string GetFullNameInternal(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
@@ -901,8 +908,7 @@ private:
void ComputeVersionedName(std::string& vName, std::string const& prefix,
std::string const& base, std::string const& suffix,
- std::string const& name,
- const char* version) const;
+ std::string const& name, cmValue version) const;
struct CompatibleInterfacesBase
{
@@ -1037,11 +1043,8 @@ private:
std::string const& config,
const cmGeneratorTarget* headTarget,
bool usage_requirements_only,
- std::vector<cmLinkItem>& items,
- std::vector<cmLinkItem>& objects,
- bool& hadHeadSensitiveCondition,
- bool& hadContextSensitiveCondition,
- bool& hadLinkLanguageSensitiveCondition) const;
+ cmLinkInterface& iface) const;
+
struct LookupLinkItemScope
{
cmLocalGenerator const* LG;
@@ -1113,8 +1116,8 @@ private:
mutable std::map<std::string, BTs<std::string>> LanguageStandardMap;
- cmProp GetPropertyWithPairedLanguageSupport(std::string const& lang,
- const char* suffix) const;
+ cmValue GetPropertyWithPairedLanguageSupport(std::string const& lang,
+ const char* suffix) const;
void ComputeLinkImplementationRuntimeLibraries(
const std::string& config, cmOptionalLinkImplementation& impl) const;
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index 79cbe443c..42bd206f7 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -7,9 +7,9 @@
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
// cmGetCMakePropertyCommand
bool cmGetCMakePropertyCommand(std::vector<std::string> const& args,
@@ -24,12 +24,12 @@ bool cmGetCMakePropertyCommand(std::vector<std::string> const& args,
std::string output = "NOTFOUND";
if (args[1] == "VARIABLES") {
- if (cmProp varsProp = status.GetMakefile().GetProperty("VARIABLES")) {
+ if (cmValue varsProp = status.GetMakefile().GetProperty("VARIABLES")) {
output = *varsProp;
}
} else if (args[1] == "MACROS") {
output.clear();
- if (cmProp macrosProp = status.GetMakefile().GetProperty("MACROS")) {
+ if (cmValue macrosProp = status.GetMakefile().GetProperty("MACROS")) {
output = *macrosProp;
}
} else if (args[1] == "COMPONENTS") {
@@ -37,7 +37,7 @@ bool cmGetCMakePropertyCommand(std::vector<std::string> const& args,
status.GetMakefile().GetGlobalGenerator()->GetInstallComponents();
output = cmJoin(*components, ";");
} else {
- cmProp prop = nullptr;
+ cmValue prop = nullptr;
if (!args[1].empty()) {
prop = status.GetMakefile().GetState()->GetGlobalProperty(args[1]);
}
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 7fbd479ac..d892cfa75 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -7,12 +7,14 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
void StoreResult(cmMakefile& makefile, std::string const& variable,
const char* prop);
+void StoreResult(cmMakefile& makefile, std::string const& variable,
+ cmValue prop);
}
// cmGetDirectoryPropertyCommand
@@ -76,7 +78,6 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
return false;
}
- const char* prop = nullptr;
if (*i == "DEFINITIONS") {
switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) {
case cmPolicies::WARN:
@@ -94,8 +95,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
break;
}
}
- prop = cmToCStr(dir->GetProperty(*i));
- StoreResult(status.GetMakefile(), variable, prop);
+ StoreResult(status.GetMakefile(), variable, dir->GetProperty(*i));
return true;
}
@@ -105,4 +105,9 @@ void StoreResult(cmMakefile& makefile, std::string const& variable,
{
makefile.AddDefinition(variable, prop ? prop : "");
}
+void StoreResult(cmMakefile& makefile, std::string const& variable,
+ cmValue prop)
+{
+ makefile.AddDefinition(variable, prop);
+}
}
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index 40e8a05d6..abe7d32a7 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -4,10 +4,10 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmGetFilenameComponentCommand
bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
@@ -22,7 +22,7 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
// Check and see if the value has been stored in the cache
// already, if so use that value
if (args.size() >= 4 && args.back() == "CACHE") {
- cmProp cacheValue = status.GetMakefile().GetDefinition(args.front());
+ cmValue cacheValue = status.GetMakefile().GetDefinition(args.front());
if (cacheValue && !cmIsNOTFOUND(*cacheValue)) {
return true;
}
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index cb657f9ee..162860a00 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetPropertyCommand.h"
+#include <cstddef>
+
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
@@ -18,6 +20,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
+#include "cmValue.h"
#include "cmake.h"
class cmMessenger;
@@ -32,10 +35,6 @@ enum OutType
OutSet
};
-// Implementation of result storage.
-bool StoreResult(OutType infoType, cmMakefile& makefile,
- const std::string& variable, const char* value);
-
// Implementation of each property type.
bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
@@ -253,8 +252,10 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args,
namespace {
+// Implementation of result storage.
+template <typename ValueType>
bool StoreResult(OutType infoType, cmMakefile& makefile,
- const std::string& variable, const char* value)
+ const std::string& variable, ValueType value)
{
if (infoType == OutSet) {
makefile.AddDefinition(variable, value ? "1" : "0");
@@ -268,6 +269,12 @@ bool StoreResult(OutType infoType, cmMakefile& makefile,
}
return true;
}
+template <>
+bool StoreResult(OutType infoType, cmMakefile& makefile,
+ const std::string& variable, std::nullptr_t value)
+{
+ return StoreResult(infoType, makefile, variable, cmValue(value));
+}
bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
@@ -280,9 +287,8 @@ bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
// Get the property.
cmake* cm = status.GetMakefile().GetCMakeInstance();
- return StoreResult(
- infoType, status.GetMakefile(), variable,
- cmToCStr(cm->GetState()->GetGlobalProperty(propertyName)));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ cm->GetState()->GetGlobalProperty(propertyName));
}
bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
@@ -329,7 +335,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
// Get the property.
return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(mf->GetProperty(propertyName)));
+ mf->GetProperty(propertyName));
}
bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
@@ -361,12 +367,11 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
}
cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
cmMessenger* messenger = status.GetMakefile().GetMessenger();
- cmProp prop = target->GetComputedProperty(propertyName, messenger, bt);
+ cmValue prop = target->GetComputedProperty(propertyName, messenger, bt);
if (!prop) {
prop = target->GetProperty(propertyName);
}
- return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(prop));
+ return StoreResult(infoType, status.GetMakefile(), variable, prop);
}
status.SetError(cmStrCat("could not find TARGET ", name,
". Perhaps it has not yet been created."));
@@ -391,7 +396,7 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
if (cmSourceFile* sf =
directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
return StoreResult(infoType, status.GetMakefile(), variable,
- cmToCStr(sf->GetPropertyForUser(propertyName)));
+ sf->GetPropertyForUser(propertyName));
}
status.SetError(
cmStrCat("given SOURCE name that could not be found or created: ",
@@ -428,9 +433,8 @@ bool HandleVariableMode(cmExecutionStatus& status, const std::string& name,
return false;
}
- return StoreResult(
- infoType, status.GetMakefile(), variable,
- cmToCStr(status.GetMakefile().GetDefinition(propertyName)));
+ return StoreResult(infoType, status.GetMakefile(), variable,
+ status.GetMakefile().GetDefinition(propertyName));
}
bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
@@ -442,12 +446,12 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
return false;
}
- cmProp value = nullptr;
+ cmValue value = nullptr;
if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
value = status.GetMakefile().GetState()->GetCacheEntryProperty(
name, propertyName);
}
- StoreResult(infoType, status.GetMakefile(), variable, cmToCStr(value));
+ StoreResult(infoType, status.GetMakefile(), variable, value);
return true;
}
diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx
index 5301b6618..40ae1126c 100644
--- a/Source/cmGetSourceFilePropertyCommand.cxx
+++ b/Source/cmGetSourceFilePropertyCommand.cxx
@@ -4,9 +4,9 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
+#include "cmValue.h"
bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -58,7 +58,7 @@ bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args,
}
if (sf) {
- cmProp prop = nullptr;
+ cmValue prop = nullptr;
if (!args[property_arg_index].empty()) {
prop = sf->GetPropertyForUser(args[property_arg_index]);
}
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 78a17d2c3..12c82216b 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -10,8 +10,8 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmTarget.h"
+#include "cmValue.h"
class cmMessenger;
@@ -42,7 +42,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
}
}
} else if (!args[2].empty()) {
- cmProp prop_cstr = nullptr;
+ cmValue prop_cstr = nullptr;
cmListFileBacktrace bt = mf.GetBacktrace();
cmMessenger* messenger = mf.GetMessenger();
prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
@@ -62,6 +62,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
case cmPolicies::WARN:
issueMessage = true;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0045) << "\n";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
@@ -69,6 +70,7 @@ bool cmGetTargetPropertyCommand(std::vector<std::string> const& args,
case cmPolicies::NEW:
issueMessage = true;
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (issueMessage) {
e << "get_target_property() called with non-existent target \""
diff --git a/Source/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index cf8c1d5fa..a4ac9f686 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -5,6 +5,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmTest.h"
+#include "cmValue.h"
bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
cmExecutionStatus& status)
@@ -19,12 +20,12 @@ bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
cmMakefile& mf = status.GetMakefile();
cmTest* test = mf.GetTest(testName);
if (test) {
- const char* prop = nullptr;
+ cmValue prop;
if (!args[1].empty()) {
prop = test->GetProperty(args[1]);
}
if (prop) {
- mf.AddDefinition(var, prop);
+ mf.AddDefinition(var, prop->c_str());
return true;
}
}
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 32238e4bd..47cefaeaa 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -19,7 +19,6 @@
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceGroup.h"
@@ -29,6 +28,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
: GeneratorTarget(target)
@@ -43,7 +43,7 @@ cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target)
#endif
{
// Store the configuration name that is being used
- if (cmProp config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
+ if (cmValue config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE")) {
// Use the build type given by the user.
this->ConfigName = *config;
} else {
@@ -376,7 +376,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
#ifdef _WIN32
std::string check_error = "if %errorlevel% neq 0 exit /b %errorlevel%";
#else
- std::string check_error = "if [[ $? -ne 0 ]]; then exit 1; fi";
+ std::string check_error = "if [ $? -ne 0 ]; then exit 1; fi";
#endif
#ifdef _WIN32
@@ -453,7 +453,7 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty(
std::ostream& fout, const cmSourceFile* sf, std::string const& propName,
std::string const& propFlag)
{
- cmProp prop = sf->GetProperty(propName);
+ cmValue prop = sf->GetProperty(propName);
if (prop) {
std::vector<std::string> list = cmExpandedList(*prop);
for (const std::string& p : list) {
@@ -705,7 +705,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandLine(
void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
std::ostream& fout, const cmSourceFile* sourceFile)
{
- cmProp rawLangProp = sourceFile->GetProperty("LANGUAGE");
+ cmValue rawLangProp = sourceFile->GetProperty("LANGUAGE");
if (rawLangProp) {
std::string sourceLangProp(*rawLangProp);
std::string const& extension = sourceFile->GetExtension();
@@ -717,7 +717,7 @@ void cmGhsMultiTargetGenerator::WriteObjectLangOverride(
bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp()
{
- if (cmProp p = this->GeneratorTarget->GetProperty("ghs_integrity_app")) {
+ if (cmValue p = this->GeneratorTarget->GetProperty("ghs_integrity_app")) {
return cmIsOn(*p);
}
std::vector<cmSourceFile*> sources;
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 9e5bbca00..3ae66f0ab 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -11,13 +11,12 @@
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
-
-class cmake;
+#include "cmSystemTools.h"
+#include "cmValue.h"
+#include "cmake.h"
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
: cmGlobalGenerator(cm)
@@ -48,7 +47,7 @@ cmGlobalCommonGenerator::ComputeDirectoryTargets() const
DirectoryTarget::Target t;
t.GT = gt.get();
const std::string EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
- if (cmProp exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
+ if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
for (const std::string& config : configs) {
cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config,
gt.get());
@@ -95,3 +94,33 @@ bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
}
return !t.ExcludedFromAllInConfigs.empty();
}
+
+std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
+{
+ // If generating for an extra IDE, the edit_cache target cannot
+ // launch a terminal-interactive tool, so always use cmake-gui.
+ if (!this->GetExtraGeneratorName().empty()) {
+ return cmSystemTools::GetCMakeGUICommand();
+ }
+
+ // Use an internal cache entry to track the latest dialog used
+ // to edit the cache, and use that for the edit_cache target.
+ cmake* cm = this->GetCMakeInstance();
+ std::string editCacheCommand = cm->GetCMakeEditCommand();
+ if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
+ !editCacheCommand.empty()) {
+ if (this->SupportsDirectConsole() && editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
+ }
+ if (editCacheCommand.empty()) {
+ editCacheCommand = cmSystemTools::GetCMakeGUICommand();
+ }
+ if (!editCacheCommand.empty()) {
+ cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand,
+ "Path to cache edit program executable.",
+ cmStateEnums::INTERNAL);
+ }
+ }
+ cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
+ return edit_cmd ? *edit_cmd : std::string();
+}
diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h
index 2aa9d2782..fed9ce81b 100644
--- a/Source/cmGlobalCommonGenerator.h
+++ b/Source/cmGlobalCommonGenerator.h
@@ -42,4 +42,9 @@ public:
std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const;
bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t,
const std::string& config);
+
+protected:
+ virtual bool SupportsDirectConsole() const { return true; }
+ const char* GetEditCacheTargetName() const override { return "edit_cache"; }
+ std::string GetEditCacheCommand() const override;
};
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 919377812..9914902ef 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -44,12 +44,12 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmWorkingDirectory.h"
#include "cmake.h"
@@ -199,7 +199,7 @@ std::string cmGlobalGenerator::SelectMakeProgram(
{
std::string makeProgram = inMakeProgram;
if (cmIsOff(makeProgram)) {
- cmProp makeProgramCSTR =
+ cmValue makeProgramCSTR =
this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
if (cmIsOff(makeProgramCSTR)) {
makeProgram = makeDefault;
@@ -235,14 +235,14 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
if (!optional && (path.empty() || !cmSystemTools::FileExists(path))) {
return;
}
- cmProp cname =
+ cmValue cname =
this->GetCMakeInstance()->GetState()->GetInitializedCacheValue(langComp);
// Split compiler from arguments
std::vector<std::string> cnameArgVec;
if (cname && !cname->empty()) {
cmExpandList(*cname, cnameArgVec);
- cname = &cnameArgVec.front();
+ cname = cmValue(cnameArgVec.front());
}
std::string changeVars;
@@ -258,7 +258,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
cmSystemTools::ConvertToUnixSlashes(cnameString);
cmSystemTools::ConvertToUnixSlashes(pathString);
if (cnameString != pathString) {
- cmProp cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ cmValue cvars = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"__CMAKE_DELETE_CACHE_CHANGE_VARS_");
if (cvars) {
changeVars += *cvars;
@@ -498,6 +498,18 @@ bool cmGlobalGenerator::CheckLanguages(
void cmGlobalGenerator::EnableLanguage(
std::vector<std::string> const& languages, cmMakefile* mf, bool optional)
{
+ if (!this->IsMultiConfig()) {
+ std::string envBuildType;
+ if (!mf->GetDefinition("CMAKE_BUILD_TYPE") &&
+ cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) {
+ mf->AddCacheDefinition(
+ "CMAKE_BUILD_TYPE", envBuildType,
+ "Choose the type of build. Options include: empty, "
+ "Debug, Release, RelWithDebInfo, MinSizeRel.",
+ cmStateEnums::STRING);
+ }
+ }
+
if (languages.empty()) {
cmSystemTools::Error("EnableLanguage must have a lang specified!");
cmSystemTools::SetFatalErrorOccured();
@@ -581,16 +593,6 @@ void cmGlobalGenerator::EnableLanguage(
}
}
- if (readCMakeSystem) {
- // Find the native build tool for this generator.
- // This has to be done early so that MSBuild can be used to examine the
- // cross-compilation environment.
- if (this->GetFindMakeProgramStage() == FindMakeProgramStage::Early &&
- !this->FindMakeProgram(mf)) {
- return;
- }
- }
-
// Load the CMakeDetermineSystem.cmake file and find out
// what platform we are running on
if (!mf->GetDefinition("CMAKE_SYSTEM")) {
@@ -664,8 +666,7 @@ void cmGlobalGenerator::EnableLanguage(
}
// Find the native build tool for this generator.
- if (this->GetFindMakeProgramStage() == FindMakeProgramStage::Late &&
- !this->FindMakeProgram(mf)) {
+ if (!this->FindMakeProgram(mf)) {
return;
}
}
@@ -789,7 +790,7 @@ void cmGlobalGenerator::EnableLanguage(
std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
std::ostringstream noCompiler;
- cmProp compilerFile = mf->GetDefinition(compilerName);
+ cmValue compilerFile = mf->GetDefinition(compilerName);
if (!cmNonempty(compilerFile) || cmIsNOTFOUND(*compilerFile)) {
/* clang-format off */
noCompiler <<
@@ -826,7 +827,7 @@ void cmGlobalGenerator::EnableLanguage(
cmSystemTools::RemoveFile(compilerLangFile);
if (!this->CMakeInstance->GetIsInTryCompile()) {
this->PrintCompilerAdvice(noCompiler, lang,
- cmToCStr(mf->GetDefinition(compilerEnv)));
+ mf->GetDefinition(compilerEnv));
mf->IssueMessage(MessageType::FATAL_ERROR, noCompiler.str());
fatalError = true;
}
@@ -910,7 +911,7 @@ void cmGlobalGenerator::EnableLanguage(
void cmGlobalGenerator::PrintCompilerAdvice(std::ostream& os,
std::string const& lang,
- const char* envVar) const
+ cmValue envVar) const
{
// Subclasses override this method if they do not support this advice.
os << "Tell CMake where to find the compiler by setting ";
@@ -953,6 +954,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
mf->IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025));
+ break;
case cmPolicies::NEW:
// NEW behavior is to keep AppleClang.
break;
@@ -1019,6 +1021,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(
mf->IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0089));
+ break;
case cmPolicies::NEW:
// NEW behavior is to keep AppleClang.
break;
@@ -1105,7 +1108,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
}
std::string linkerPrefVar = "CMAKE_" + l + "_LINKER_PREFERENCE";
- cmProp linkerPref = mf->GetDefinition(linkerPrefVar);
+ cmValue linkerPref = mf->GetDefinition(linkerPrefVar);
int preference = 0;
if (cmNonempty(linkerPref)) {
if (sscanf(linkerPref->c_str(), "%d", &preference) != 1) {
@@ -1131,7 +1134,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
this->LanguageToLinkerPreference[l] = preference;
std::string outputExtensionVar = "CMAKE_" + l + "_OUTPUT_EXTENSION";
- if (cmProp p = mf->GetDefinition(outputExtensionVar)) {
+ if (cmValue p = mf->GetDefinition(outputExtensionVar)) {
std::string outputExtension = *p;
this->LanguageToOutputExtension[l] = outputExtension;
this->OutputExtensions[outputExtension] = outputExtension;
@@ -1167,10 +1170,10 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
}
}
-const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
+cmValue cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
{
assert(!this->Makefiles.empty());
- return cmToCStr(this->Makefiles[0]->GetDefinition(name));
+ return this->Makefiles[0]->GetDefinition(name);
}
bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const
@@ -1183,7 +1186,7 @@ std::string cmGlobalGenerator::GetSafeGlobalSetting(
std::string const& name) const
{
assert(!this->Makefiles.empty());
- return this->Makefiles[0]->GetSafeDefinition(name);
+ return this->Makefiles[0]->GetDefinition(name);
}
bool cmGlobalGenerator::IgnoreFile(const char* ext) const
@@ -1251,10 +1254,8 @@ void cmGlobalGenerator::Configure()
this->CreateDefaultGlobalTargets(globalTargets);
for (const auto& mf : this->Makefiles) {
- auto& targets = mf->GetTargets();
for (GlobalTargetInfo const& globalTarget : globalTargets) {
- targets.emplace(globalTarget.Name,
- this->CreateGlobalTarget(globalTarget, mf.get()));
+ this->CreateGlobalTarget(globalTarget, mf.get());
}
}
}
@@ -1401,6 +1402,9 @@ bool cmGlobalGenerator::Compute()
this->SupportsDefaultConfigs())) {
return false;
}
+ if (!this->InspectConfigTypeVariables()) {
+ return false;
+ }
// Some generators track files replaced during the Generate.
// Start with an empty vector:
@@ -1708,10 +1712,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
// Construct per-target generator information.
for (const auto& mf : this->Makefiles) {
- const cmStringRange noconfig_compile_definitions =
+ const cmBTStringRange noconfig_compile_definitions =
mf->GetCompileDefinitionsEntries();
- const cmBacktraceRange noconfig_compile_definitions_bts =
- mf->GetCompileDefinitionsBacktraces();
for (auto& target : mf->GetTargets()) {
cmTarget* t = &target.second;
@@ -1725,12 +1727,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
continue;
}
- {
- auto btIt = noconfig_compile_definitions_bts.begin();
- auto it = noconfig_compile_definitions.begin();
- for (; it != noconfig_compile_definitions.end(); ++it, ++btIt) {
- t->InsertCompileDefinition(*it, *btIt);
- }
+ for (auto const& def : noconfig_compile_definitions) {
+ t->InsertCompileDefinition(def);
}
cmPolicies::PolicyStatus polSt =
@@ -1742,7 +1740,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
for (std::string const& c : configs) {
std::string defPropName =
cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c));
- if (cmProp val = mf->GetProperty(defPropName)) {
+ if (cmValue val = mf->GetProperty(defPropName)) {
t->AppendProperty(defPropName, *val);
}
}
@@ -1771,9 +1769,8 @@ void cmGlobalGenerator::CreateGeneratorTargets(
std::map<cmTarget*, cmGeneratorTarget*> const& importedMap)
{
if (targetTypes == AllTargets) {
- for (auto& target : mf->GetTargets()) {
- cmTarget* t = &target.second;
- lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg));
+ for (cmTarget* target : mf->GetOrderedTargets()) {
+ lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(target, lg));
}
}
@@ -1857,7 +1854,7 @@ void cmGlobalGenerator::CheckTargetProperties()
}
}
std::vector<std::string> incs;
- cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
+ cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
if (!incDirProp) {
continue;
}
@@ -2121,7 +2118,7 @@ void cmGlobalGenerator::AddMakefile(std::unique_ptr<cmMakefile> mf)
// update progress
// estimate how many lg there will be
- cmProp numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue(
+ cmValue numGenC = this->CMakeInstance->GetState()->GetInitializedCacheValue(
"CMAKE_NUMBER_OF_MAKEFILES");
if (!numGenC) {
@@ -2180,11 +2177,10 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen,
{
this->SetConfiguredFilesPath(gen);
this->TryCompileOuterMakefile = mf;
- cmProp make =
+ cmValue make =
gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
- this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", cmToCStr(make),
- "make program",
- cmStateEnums::FILEPATH);
+ this->GetCMakeInstance()->AddCacheEntry(
+ "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH);
// copy the enabled languages
this->GetCMakeInstance()->GetState()->SetEnabledLanguages(
gen->GetCMakeInstance()->GetState()->GetEnabledLanguages());
@@ -2244,7 +2240,7 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
}
cmMakefile* mf = root->GetMakefile();
const std::string EXCLUDE_FROM_ALL = "EXCLUDE_FROM_ALL";
- if (cmProp exclude = target->GetProperty(EXCLUDE_FROM_ALL)) {
+ if (cmValue exclude = target->GetProperty(EXCLUDE_FROM_ALL)) {
// Expand the property value per configuration.
unsigned int trueCount = 0;
unsigned int falseCount = 0;
@@ -2538,7 +2534,7 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
if (this->GetPreinstallTargetName()) {
gti.Depends.emplace_back(this->GetPreinstallTargetName());
} else {
- cmProp noPackageAll =
+ cmValue noPackageAll =
mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY");
if (cmIsOff(noPackageAll)) {
gti.Depends.emplace_back(this->GetAllTargetName());
@@ -2719,7 +2715,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
if (this->GetPreinstallTargetName()) {
gti.Depends.emplace_back(this->GetPreinstallTargetName());
} else {
- cmProp noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
+ cmValue noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
if (cmIsOff(noall)) {
gti.Depends.emplace_back(this->GetAllTargetName());
}
@@ -2740,7 +2736,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
singleLine.push_back(cfgArg);
cfgArg = "-DEFFECTIVE_PLATFORM_NAME=$(EFFECTIVE_PLATFORM_NAME)";
} else {
- cfgArg += cmToCStr(mf->GetDefinition("CMAKE_CFG_INTDIR"));
+ cfgArg += *mf->GetDefinition("CMAKE_CFG_INTDIR");
}
singleLine.push_back(cfgArg);
}
@@ -2785,7 +2781,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
{
- cmProp prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ cmValue prop = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"PREDEFINED_TARGETS_FOLDER");
if (prop) {
@@ -2797,7 +2793,7 @@ std::string cmGlobalGenerator::GetPredefinedTargetsFolder() const
bool cmGlobalGenerator::UseFolderProperty() const
{
- cmProp prop =
+ cmValue prop =
this->GetCMakeInstance()->GetState()->GetGlobalProperty("USE_FOLDERS");
// If this property is defined, let the setter turn this on or off...
@@ -2812,12 +2808,19 @@ bool cmGlobalGenerator::UseFolderProperty() const
return false;
}
-cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
- cmMakefile* mf)
+void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
+ cmMakefile* mf)
{
// Package
- cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET,
- cmTarget::VisibilityNormal, mf, gti.PerConfig);
+ auto tb =
+ mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig);
+
+ // Do nothing if gti.Name is already used
+ if (!tb.second) {
+ return;
+ }
+
+ cmTarget& target = tb.first;
target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
std::vector<std::string> no_outputs;
@@ -2841,8 +2844,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
if (this->UseFolderProperty()) {
target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
}
-
- return target;
}
std::string cmGlobalGenerator::GenerateRuleFile(
@@ -3143,10 +3144,10 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
#ifndef CMAKE_BOOTSTRAP
// Check whether labels are enabled for this target.
- cmProp targetLabels = target->GetProperty("LABELS");
- cmProp directoryLabels =
+ cmValue targetLabels = target->GetProperty("LABELS");
+ cmValue directoryLabels =
target->Target->GetMakefile()->GetProperty("LABELS");
- cmProp cmakeDirectoryLabels =
+ cmValue cmakeDirectoryLabels =
target->Target->GetMakefile()->GetDefinition("CMAKE_DIRECTORY_LABELS");
if (targetLabels || directoryLabels || cmakeDirectoryLabels) {
Json::Value lj_root(Json::objectValue);
@@ -3214,7 +3215,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
std::string const& sfp = sf->ResolveFullPath();
fout << sfp << "\n";
lj_source["file"] = sfp;
- if (cmProp svalue = sf->GetProperty("LABELS")) {
+ if (cmValue svalue = sf->GetProperty("LABELS")) {
labels.clear();
Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue;
cmExpandList(*svalue, labels);
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 147146e13..96696aa8a 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -29,6 +29,7 @@
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmTransformDepfile.h"
+#include "cmValue.h"
#if !defined(CMAKE_BOOTSTRAP)
# include <cm3p/json/value.h>
@@ -152,6 +153,8 @@ public:
*/
virtual void Configure();
+ virtual bool InspectConfigTypeVariables() { return true; }
+
bool Compute();
virtual void AddExtraIDETargets() {}
@@ -308,7 +311,7 @@ public:
cmExportSetMap& GetExportSets() { return this->ExportSets; }
- const char* GetGlobalSetting(std::string const& name) const;
+ cmValue GetGlobalSetting(std::string const& name) const;
bool GlobalSettingIsOn(std::string const& name) const;
std::string GetSafeGlobalSetting(std::string const& name) const;
@@ -443,6 +446,8 @@ public:
virtual bool IsVisualStudio() const { return false; }
+ virtual bool IsVisualStudioAtLeast10() const { return false; }
+
virtual bool IsNinja() const { return false; }
/** Return true if we know the exact location of object files.
@@ -549,7 +554,7 @@ protected:
virtual bool CheckLanguages(std::vector<std::string> const& languages,
cmMakefile* mf) const;
virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const;
+ cmValue envVar) const;
virtual bool ComputeTargetDepends();
@@ -596,7 +601,7 @@ protected:
void AddGlobalTarget_RebuildCache(
std::vector<GlobalTargetInfo>& targets) const;
void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
- cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
+ void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);
std::string FindMakeProgramFile;
std::string ConfiguredFilesPath;
@@ -622,17 +627,6 @@ protected:
std::string GetPredefinedTargetsFolder() const;
- enum class FindMakeProgramStage
- {
- Early,
- Late,
- };
-
- virtual FindMakeProgramStage GetFindMakeProgramStage() const
- {
- return FindMakeProgramStage::Late;
- }
-
private:
using TargetMap = std::unordered_map<std::string, cmTarget*>;
using GeneratorTargetMap =
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 7cf3e9363..b1c0488d4 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -18,11 +18,11 @@
#include "cmLocalGenerator.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -99,7 +99,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
/* set the build tool to use */
std::string gbuild(tsp + ((tsp.back() == '/') ? "" : "/") +
DEFAULT_BUILD_PROGRAM);
- cmProp prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
+ cmValue prevTool = mf->GetDefinition("CMAKE_MAKE_PROGRAM");
/* check if the toolset changed from last generate */
if (prevTool && (gbuild != *prevTool)) {
@@ -186,8 +186,7 @@ void cmGlobalGhsMultiGenerator::EnableLanguage(
mf->AddDefinition("GHSMULTI", "1"); // identifier for user CMake files
- const char* tgtPlatform =
- cmToCStrSafe(mf->GetDefinition("GHS_TARGET_PLATFORM"));
+ const char* tgtPlatform = mf->GetDefinition("GHS_TARGET_PLATFORM")->c_str();
if (!tgtPlatform) {
cmSystemTools::Message("Green Hills MULTI: GHS_TARGET_PLATFORM not "
"specified; defaulting to \"integrity\"");
@@ -216,7 +215,7 @@ bool cmGlobalGhsMultiGenerator::FindMakeProgram(cmMakefile* /*mf*/)
void cmGlobalGhsMultiGenerator::GetToolset(cmMakefile* mf, std::string& tsd,
const std::string& ts)
{
- cmProp ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
+ cmValue ghsRoot = mf->GetDefinition("GHS_TOOLSET_ROOT");
if (cmNonempty(ghsRoot)) {
tsd = *ghsRoot;
@@ -334,7 +333,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
fout << "# Top Level Project File\n";
// Specify BSP option if supplied by user
- cmProp bspName =
+ cmValue bspName =
this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME");
if (!cmIsOff(bspName)) {
fout << " -bsp " << *bspName << '\n';
@@ -343,7 +342,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout,
// Specify OS DIR if supplied by user
// -- not all platforms require this entry in the project file
if (!cmIsOff(this->OsDir)) {
- cmProp osDirOption =
+ cmValue osDirOption =
this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION");
std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/');
fout << " ";
@@ -378,8 +377,8 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine(
std::ostream& fout, cmGeneratorTarget const* target,
std::string& rootBinaryDir)
{
- cmProp projName = target->GetProperty("GENERATOR_FILE_NAME");
- cmProp projType = target->GetProperty("GENERATOR_FILE_NAME_EXT");
+ cmValue projName = target->GetProperty("GENERATOR_FILE_NAME");
+ cmValue projType = target->GetProperty("GENERATOR_FILE_NAME_EXT");
if (projName && projType) {
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string dir = lg->GetCurrentBinaryDirectory();
@@ -564,7 +563,7 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand(
{
GeneratedMakeCommand makeCommand = {};
std::string gbuild;
- if (cmProp gbuildCached =
+ if (cmValue gbuildCached =
this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM")) {
gbuild = *gbuildCached;
}
@@ -617,7 +616,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout,
cmLocalGenerator* root)
{
fout << "macro PROJ_NAME=" << root->GetProjectName() << '\n';
- cmProp ghsGpjMacros =
+ cmValue ghsGpjMacros =
this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS");
if (ghsGpjMacros) {
std::vector<std::string> expandedList = cmExpandedList(*ghsGpjMacros);
@@ -632,15 +631,15 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
{
/* set primary target */
std::string tgt;
- cmProp t =
+ cmValue t =
this->GetCMakeInstance()->GetCacheDefinition("GHS_PRIMARY_TARGET");
if (cmNonempty(t)) {
tgt = *t;
this->GetCMakeInstance()->MarkCliAsUsed("GHS_PRIMARY_TARGET");
} else {
- cmProp a =
+ cmValue a =
this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
- cmProp p =
+ cmValue p =
this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
tgt = cmStrCat((a ? *a : ""), '_', (p ? *p : ""), ".tgt");
}
@@ -653,7 +652,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
<< "/CMakeFiles/custom_target.bod" << '\n';
/* clang-format on */
- cmProp const customization =
+ cmValue const customization =
this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION");
if (cmNonempty(customization)) {
fout << "customization="
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index fc3123a44..40deebb04 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -39,8 +39,9 @@ void cmGlobalJOMMakefileGenerator::GetDocumentation(
entry.Brief = "Generates JOM makefiles.";
}
-void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
- std::ostream& os, std::string const& lang, const char* envVar) const
+void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os,
+ std::string const& lang,
+ cmValue envVar) const
{
if (lang == "CXX" || lang == "C") {
/* clang-format off */
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 2d58f9119..58860dd64 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -50,5 +50,5 @@ protected:
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const override;
+ cmValue envVar) const override;
};
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index f08b1da36..a038f871e 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -42,7 +42,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
return false;
}
- if (cmProp nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
+ if (cmValue nmakeCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
std::vector<std::string> command{ *nmakeCommand, "-?" };
std::string out;
std::string err;
@@ -70,7 +70,7 @@ bool cmGlobalNMakeMakefileGenerator::FindMakeProgram(cmMakefile* mf)
void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
{
this->NMakeSupportsUTF8 = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NMakeVersion.c_str(), "9");
+ cmSystemTools::OP_LESS, this->NMakeVersion, "9");
}
void cmGlobalNMakeMakefileGenerator::GetDocumentation(
@@ -81,7 +81,7 @@ void cmGlobalNMakeMakefileGenerator::GetDocumentation(
}
void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
- std::ostream& os, std::string const& lang, const char* envVar) const
+ std::ostream& os, std::string const& lang, cmValue envVar) const
{
if (lang == "CXX" || lang == "C") {
/* clang-format off */
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 402b89fda..4f202b5a4 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -61,5 +61,5 @@ private:
void CheckNMakeFeatures();
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
- const char* envVar) const override;
+ cmValue envVar) const override;
};
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 971a462a6..7122b9f8f 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -35,7 +35,6 @@
#include "cmMessageType.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmScanDepFormat.h"
#include "cmState.h"
@@ -46,6 +45,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -382,7 +382,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
if (restat) {
vars["restat"] = "1";
}
- if (uses_terminal && this->SupportsConsolePool()) {
+ if (uses_terminal && this->SupportsDirectConsole()) {
vars["pool"] = "console";
} else if (!job_pool.empty()) {
vars["pool"] = job_pool;
@@ -558,9 +558,8 @@ void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
void cmGlobalNinjaGenerator::Generate()
{
// Check minimum Ninja version.
- if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- this->NinjaVersion.c_str(),
- RequiredNinjaVersion().c_str())) {
+ if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersion())) {
std::ostringstream msg;
msg << "The detected version of Ninja (" << this->NinjaVersion;
msg << ") is less than the version of Ninja required by CMake (";
@@ -569,9 +568,6 @@ void cmGlobalNinjaGenerator::Generate()
msg.str());
return;
}
- if (!this->InspectConfigTypeVariables()) {
- return;
- }
if (!this->OpenBuildFileStreams()) {
return;
}
@@ -695,7 +691,7 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
if (!this->cmGlobalGenerator::FindMakeProgram(mf)) {
return false;
}
- if (cmProp ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
+ if (cmValue ninjaCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
this->NinjaCommand = *ninjaCommand;
std::vector<std::string> command;
command.push_back(this->NinjaCommand);
@@ -721,21 +717,21 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf)
void cmGlobalNinjaGenerator::CheckNinjaFeatures()
{
- this->NinjaSupportsConsolePool = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForConsolePool().c_str());
+ this->NinjaSupportsConsolePool =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForConsolePool());
this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts().c_str());
- this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForManifestRestat().c_str());
- this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForMultilineDepfile().c_str());
- this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForDyndeps().c_str());
+ cmSystemTools::OP_LESS, this->NinjaVersion,
+ cmGlobalNinjaGenerator::RequiredNinjaVersionForImplicitOuts());
+ this->NinjaSupportsManifestRestat =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForManifestRestat());
+ this->NinjaSupportsMultilineDepfile =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForMultilineDepfile());
+ this->NinjaSupportsDyndeps =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForDyndeps());
if (!this->NinjaSupportsDyndeps) {
// The ninja version number is not new enough to have upstream support.
// Our ninja branch adds ".dyndep-#" to its version number,
@@ -753,21 +749,21 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures()
}
this->NinjaSupportsUnconditionalRecompactTool =
!cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForUnconditionalRecompactTool().c_str());
- this->NinjaSupportsRestatTool = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForRestatTool().c_str());
- this->NinjaSupportsMultipleOutputs = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForMultipleOutputs().c_str());
+ cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForUnconditionalRecompactTool());
+ this->NinjaSupportsRestatTool =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForRestatTool());
+ this->NinjaSupportsMultipleOutputs =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForMultipleOutputs());
this->NinjaSupportsMetadataOnRegeneration = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForMetadataOnRegeneration().c_str());
+ cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForMetadataOnRegeneration());
#ifdef _WIN32
- this->NinjaSupportsCodePage = !cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, this->NinjaVersion.c_str(),
- RequiredNinjaVersionForCodePage().c_str());
+ this->NinjaSupportsCodePage =
+ !cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, this->NinjaVersion,
+ RequiredNinjaVersionForCodePage());
if (this->NinjaSupportsCodePage) {
this->CheckNinjaCodePage();
} else {
@@ -920,14 +916,7 @@ void cmGlobalNinjaGenerator::EnableLanguage(
std::vector<std::string> const& langs, cmMakefile* mf, bool optional)
{
if (this->IsMultiConfig()) {
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, only "
- "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything "
- "else will be ignored",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;RelWithDebInfo");
}
this->cmGlobalGenerator::EnableLanguage(langs, mf, optional);
@@ -936,29 +925,21 @@ void cmGlobalNinjaGenerator::EnableLanguage(
continue;
}
this->ResolveLanguageCompiler(l, mf, optional);
- }
#ifdef _WIN32
- const bool clangGnuMode =
- ((mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") &&
- (mf->GetSafeDefinition("CMAKE_C_COMPILER_FRONTEND_VARIANT") == "GNU")) ||
- ((mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") &&
- (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_FRONTEND_VARIANT") == "GNU"));
-
- if (clangGnuMode ||
- ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") &&
- (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") &&
- (mf->IsOn("CMAKE_COMPILER_IS_MINGW") ||
- (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") ||
- (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") ||
- (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") ||
- (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") ||
- (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "ARMClang") ||
- (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "ARMClang") ||
- (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") ||
- (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) {
- this->UsingGCCOnWindows = true;
- }
+ std::string const& compilerId =
+ mf->GetSafeDefinition(cmStrCat("CMAKE_", l, "_COMPILER_ID"));
+ std::string const& simulateId =
+ mf->GetSafeDefinition(cmStrCat("CMAKE_", l, "_SIMULATE_ID"));
+ std::string const& compilerFrontendVariant = mf->GetSafeDefinition(
+ cmStrCat("CMAKE_", l, "_COMPILER_FRONTEND_VARIANT"));
+ if ((compilerId == "Clang" && compilerFrontendVariant == "GNU") ||
+ (simulateId != "MSVC" &&
+ (compilerId == "GNU" || compilerId == "QCC" ||
+ cmHasLiteralSuffix(compilerId, "Clang")))) {
+ this->UsingGCCOnWindows = true;
+ }
#endif
+ }
}
// Implemented by:
@@ -1021,13 +1002,6 @@ bool cmGlobalNinjaGenerator::HasRule(const std::string& name)
// Private virtual overrides
-std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const
-{
- // Ninja by design does not run interactive tools in the terminal,
- // so our only choice is cmake-gui.
- return cmSystemTools::GetCMakeGUICommand();
-}
-
void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
@@ -1286,7 +1260,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
break;
}
}
- // FALLTHROUGH
+ CM_FALLTHROUGH;
case cmStateEnums::EXECUTABLE: {
outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
config, cmStateEnums::RuntimeBinaryArtifact, realname)));
@@ -1298,7 +1272,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
break;
}
}
- // FALLTHROUGH
+ CM_FALLTHROUGH;
case cmStateEnums::GLOBAL_TARGET:
case cmStateEnums::INTERFACE_LIBRARY:
case cmStateEnums::UTILITY: {
@@ -1849,7 +1823,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
- if (this->SupportsConsolePool()) {
+ if (this->SupportsDirectConsole()) {
reBuild.Variables["pool"] = "console";
}
@@ -1943,7 +1917,7 @@ std::string cmGlobalNinjaGenerator::NinjaCmd() const
return "ninja";
}
-bool cmGlobalNinjaGenerator::SupportsConsolePool() const
+bool cmGlobalNinjaGenerator::SupportsDirectConsole() const
{
return this->NinjaSupportsConsolePool;
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index bb4ce2bf2..84fc06c1c 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -220,7 +220,6 @@ public:
{
return "package_source";
}
- const char* GetEditCacheTargetName() const override { return "edit_cache"; }
const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
@@ -406,7 +405,7 @@ public:
return "1.10.2";
}
static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
- bool SupportsConsolePool() const;
+ bool SupportsDirectConsole() const override;
bool SupportsImplicitOuts() const;
bool SupportsManifestRestat() const;
bool SupportsMultilineDepfile() const;
@@ -482,14 +481,11 @@ protected:
const std::set<std::string>& all, const std::set<std::string>& defaults,
const std::vector<std::string>& items);
- virtual bool InspectConfigTypeVariables() { return true; }
-
std::set<std::string> CrossConfigs;
std::set<std::string> DefaultConfigs;
std::string DefaultFileConfig;
private:
- std::string GetEditCacheCommand() const override;
bool FindMakeProgram(cmMakefile* mf) override;
void CheckNinjaFeatures();
void CheckNinjaCodePage();
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 9c3de1eed..055654091 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -20,12 +20,12 @@
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetDepend.h"
+#include "cmValue.h"
#include "cmake.h"
cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm)
@@ -78,36 +78,6 @@ void cmGlobalUnixMakefileGenerator3::GetDocumentation(
entry.Brief = "Generates standard UNIX makefiles.";
}
-std::string cmGlobalUnixMakefileGenerator3::GetEditCacheCommand() const
-{
- // If generating for an extra IDE, the edit_cache target cannot
- // launch a terminal-interactive tool, so always use cmake-gui.
- if (!this->GetExtraGeneratorName().empty()) {
- return cmSystemTools::GetCMakeGUICommand();
- }
-
- // Use an internal cache entry to track the latest dialog used
- // to edit the cache, and use that for the edit_cache target.
- cmake* cm = this->GetCMakeInstance();
- std::string editCacheCommand = cm->GetCMakeEditCommand();
- if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
- !editCacheCommand.empty()) {
- if (editCacheCommand.empty()) {
- editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
- }
- if (editCacheCommand.empty()) {
- editCacheCommand = cmSystemTools::GetCMakeGUICommand();
- }
- if (!editCacheCommand.empty()) {
- cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(),
- "Path to cache edit program executable.",
- cmStateEnums::INTERNAL);
- }
- }
- cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
- return edit_cmd ? *edit_cmd : std::string();
-}
-
void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
cmGeneratorTarget* gt) const
{
@@ -714,7 +684,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
}
bool targetMessages = true;
- if (cmProp tgtMsg =
+ if (cmValue tgtMsg =
this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"TARGET_MESSAGES")) {
targetMessages = cmIsOn(*tgtMsg);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 7c950cca1..94ee47633 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -228,7 +228,6 @@ protected:
{
return "package_source";
}
- const char* GetEditCacheTargetName() const override { return "edit_cache"; }
const char* GetRebuildCacheTargetName() const override
{
return "rebuild_cache";
@@ -278,7 +277,6 @@ protected:
private:
const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; }
- std::string GetEditCacheCommand() const override;
std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
cmStateSnapshot::StrictWeakOrder>
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index fdb71554c..6cab49269 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -88,7 +88,7 @@ public:
void GetDocumentation(cmDocumentationEntry& entry) const override
{
entry.Name = std::string(vs10generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2010 project files. "
+ entry.Brief = "Deprecated. Generates Visual Studio 2010 project files. "
"Optional [arch] can be \"Win64\" or \"IA64\".";
}
@@ -139,7 +139,6 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
"ProductDir",
vc10Express, cmSystemTools::KeyWOW64_32);
this->CudaEnabled = false;
- this->MSBuildCommandInitialized = false;
{
std::string envPlatformToolset;
if (cmSystemTools::GetEnv("PlatformToolset", envPlatformToolset) &&
@@ -581,6 +580,13 @@ bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf)
this->DefaultPlatformToolset = this->SelectWindowsCEToolset();
+ if (this->GetVersion() == cmGlobalVisualStudioGenerator::VS12) {
+ // VS 12 .NET CF defaults to .NET framework 3.9 for Windows CE.
+ this->DefaultTargetFrameworkVersion = "v3.9";
+ this->DefaultTargetFrameworkIdentifier = "WindowsEmbeddedCompact";
+ this->DefaultTargetFrameworkTargetsVersion = "v8.0";
+ }
+
return true;
}
@@ -857,6 +863,12 @@ std::string const& cmGlobalVisualStudio10Generator::GetMSBuildCommand()
return this->MSBuildCommand;
}
+cm::optional<std::string>
+cmGlobalVisualStudio10Generator::FindMSBuildCommandEarly(cmMakefile*)
+{
+ return this->GetMSBuildCommand();
+}
+
std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
{
std::string msbuild;
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index b7ae1eecf..6e6239065 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -20,6 +20,8 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator
public:
static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory();
+ bool IsVisualStudioAtLeast10() const override { return true; }
+
bool MatchesGeneratorName(const std::string& name) const override;
bool SetSystemName(std::string const& s, cmMakefile* mf) override;
@@ -132,6 +134,8 @@ public:
bool GetSupportsUnityBuilds() const { return this->SupportsUnityBuilds; }
+ virtual cm::optional<std::string> FindMSBuildCommandEarly(cmMakefile* mf);
+
bool FindMakeProgram(cmMakefile* mf) override;
bool IsIPOSupported() const override { return true; }
@@ -222,6 +226,7 @@ protected:
bool SystemIsWindowsPhone = false;
bool SystemIsWindowsStore = false;
bool SystemIsAndroid = false;
+ bool MSBuildCommandInitialized = false;
private:
class Factory;
@@ -243,7 +248,6 @@ private:
LongestSourcePath LongestSource;
std::string MSBuildCommand;
- bool MSBuildCommandInitialized;
std::set<std::string> AndroidExecutableWarnings;
virtual std::string FindMSBuildCommand();
std::string FindDevEnvCommand() override;
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index b46f1b9b0..ff1642f8b 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -239,7 +239,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion(
{
// if the given value is set, it can either be OFF/FALSE or a valid SDK
// string
- if (cmProp value = mf->GetDefinition(
+ if (cmValue value = mf->GetDefinition(
"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM")) {
// If the value is some off/false value, then there is NO maximum set.
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 0083c407d..50975ffdf 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -102,7 +102,7 @@ void cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
ext = ".csproj";
project = "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"";
}
- cmProp targetExt = t->GetProperty("GENERATOR_FILE_NAME_EXT");
+ cmValue targetExt = t->GetProperty("GENERATOR_FILE_NAME_EXT");
if (targetExt) {
ext = *targetExt;
}
@@ -157,11 +157,11 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio71Generator::WriteExternalProject(
std::ostream& fout, const std::string& name, const std::string& location,
- const char* typeGuid,
- const std::set<BT<std::pair<std::string, bool>>>& depends)
+ cmValue typeGuid, const std::set<BT<std::pair<std::string, bool>>>& depends)
{
fout << "Project(\"{"
- << (typeGuid ? typeGuid : this->ExternalProjectType(location))
+ << (typeGuid ? typeGuid
+ : std::string(this->ExternalProjectType(location)))
<< "}\") = \"" << name << "\", \""
<< this->ConvertToSolutionPath(location) << "\", \"{"
<< this->GetGUID(name) << "}\"\n";
@@ -198,8 +198,8 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations(
std::vector<std::string> mapConfig;
const char* dstConfig = i.c_str();
if (target.GetProperty("EXTERNAL_MSPROJECT")) {
- if (cmProp m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
- cmSystemTools::UpperCase(i))) {
+ if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
+ cmSystemTools::UpperCase(i))) {
cmExpandList(*m, mapConfig);
if (!mapConfig.empty()) {
dstConfig = mapConfig[0].c_str();
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 7d3819966..cb3b8c13b 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -33,7 +33,7 @@ protected:
const std::string& platformMapping = "") override;
void WriteExternalProject(
std::ostream& fout, const std::string& name, const std::string& path,
- const char* typeGuid,
+ cmValue typeGuid,
const std::set<BT<std::pair<std::string, bool>>>& depends) override;
// Folders are not supported by VS 7.1.
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 0c85a044e..6876e6179 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -37,6 +37,7 @@ static cmVS7FlagTable cmVS7ExtraFlagTable[] = {
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
{ "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
cmVS7FlagTable::UserValueRequired },
+ { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 },
{ "WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true",
0 },
@@ -107,14 +108,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage(
{
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo");
// Create list of configurations requested by user's cache, if any.
this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional);
@@ -303,6 +297,25 @@ void cmGlobalVisualStudio7Generator::Generate()
this->CallVisualStudioMacro(MacroReload,
GetSLNFile(this->LocalGenerators[0].get()));
}
+
+ if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) {
+ std::string cmakeWarnVS10;
+ if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue(
+ "CMAKE_WARN_VS10")) {
+ this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10");
+ cmakeWarnVS10 = *cached;
+ } else {
+ cmSystemTools::GetEnv("CMAKE_WARN_VS10", cmakeWarnVS10);
+ }
+ if (cmakeWarnVS10.empty() || !cmIsOff(cmakeWarnVS10)) {
+ this->CMakeInstance->IssueMessage(
+ MessageType::WARNING,
+ "The \"Visual Studio 10 2010\" generator is deprecated "
+ "and will be removed in a future version of CMake."
+ "\n"
+ "Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.");
+ }
+ }
}
void cmGlobalVisualStudio7Generator::OutputSLNFile(
@@ -342,17 +355,17 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
if (!target->IsInBuildSystem()) {
continue;
}
- cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT");
+ cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT");
if (expath) {
std::set<std::string> allConfigurations(configs.begin(), configs.end());
- cmProp mapping = target->GetProperty("VS_PLATFORM_MAPPING");
+ cmValue mapping = target->GetProperty("VS_PLATFORM_MAPPING");
this->WriteProjectConfigurations(fout, target->GetName(), *target,
configs, allConfigurations,
mapping ? *mapping : "");
} else {
const std::set<std::string>& configsPartOfDefaultBuild =
this->IsPartOfDefaultBuild(configs, projectTargets, target);
- cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName) {
this->WriteProjectConfigurations(fout, *vcprojName, *target, configs,
configsPartOfDefaultBuild);
@@ -374,18 +387,17 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
bool written = false;
// handle external vc project files
- cmProp expath = target->GetProperty("EXTERNAL_MSPROJECT");
+ cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT");
if (expath) {
std::string project = target->GetName();
std::string location = *expath;
- this->WriteExternalProject(
- fout, project, location,
- cmToCStr(target->GetProperty("VS_PROJECT_TYPE")),
- target->GetUtilities());
+ this->WriteExternalProject(fout, project, location,
+ target->GetProperty("VS_PROJECT_TYPE"),
+ target->GetUtilities());
written = true;
} else {
- cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName) {
cmLocalGenerator* lg = target->GetLocalGenerator();
std::string dir = lg->GetCurrentBinaryDirectory();
@@ -438,7 +450,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends(
if (!target->IsInBuildSystem()) {
continue;
}
- cmProp vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
+ cmValue vcprojName = target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName) {
std::string dir =
target->GetLocalGenerator()->GetCurrentSourceDirectory();
@@ -526,7 +538,7 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
extensibilityAddInsOverridden = true;
}
fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
- cmProp p = root->GetMakefile()->GetProperty(it);
+ cmValue p = root->GetMakefile()->GetProperty(it);
std::vector<std::string> keyValuePairs = cmExpandedList(p ? *p : "");
for (std::string const& itPair : keyValuePairs) {
const std::string::size_type posEqual = itPair.find('=');
@@ -625,7 +637,7 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name)
{
std::string const& guidStoreName = name + "_GUID_CMAKE";
- if (cmProp storedGUID =
+ if (cmValue storedGUID =
this->CMakeInstance->GetCacheDefinition(guidStoreName)) {
return *storedGUID;
}
@@ -675,7 +687,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
"CMAKE_VS_INCLUDE_" + t + "_TO_DEFAULT_BUILD";
// inspect CMAKE_VS_INCLUDE_<t>_TO_DEFAULT_BUILD properties
for (std::string const& i : configs) {
- cmProp propertyValue =
+ cmValue propertyValue =
target->Target->GetMakefile()->GetDefinition(propertyName);
if (propertyValue &&
cmIsOn(cmGeneratorExpression::Evaluate(
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 148762eac..8e762cf90 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -6,6 +6,7 @@
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
+#include "cmValue.h"
class cmTarget;
struct cmIDEFlagTable;
@@ -142,7 +143,7 @@ protected:
virtual void WriteExternalProject(
std::ostream& fout, const std::string& name, const std::string& path,
- const char* typeGuid,
+ cmValue typeGuid,
const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0;
std::string ConvertToSolutionPath(const std::string& path);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index b19212e47..1e45813bb 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -67,12 +67,55 @@ void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
{
- if (!this->PlatformInGeneratorName) {
- this->GeneratorPlatform = p;
- return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
- } else {
+ if (this->PlatformInGeneratorName) {
+ // This is an old-style generator name that contains the platform name.
+ // No explicit platform specification is supported, so pass it through
+ // to our base class implementation, which errors on non-empty platforms.
return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform(p, mf);
}
+
+ this->GeneratorPlatform = p;
+
+ // FIXME: Add CMAKE_GENERATOR_PLATFORM field to set the framework.
+ // For now, just report the generator's default, if any.
+ if (cm::optional<std::string> const& targetFrameworkVersion =
+ this->GetTargetFrameworkVersion()) {
+ mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_VERSION",
+ *targetFrameworkVersion);
+ }
+ if (cm::optional<std::string> const& targetFrameworkIdentifier =
+ this->GetTargetFrameworkIdentifier()) {
+ mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER",
+ *targetFrameworkIdentifier);
+ }
+ if (cm::optional<std::string> const& targetFrameworkTargetsVersion =
+ this->GetTargetFrameworkTargetsVersion()) {
+ mf->AddDefinition("CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION",
+ *targetFrameworkTargetsVersion);
+ }
+
+ // The generator name does not contain the platform name, and so supports
+ // explicit platform specification. We handled that above, so pass an
+ // empty platform name to our base class implementation so it does not error.
+ return this->cmGlobalVisualStudio7Generator::SetGeneratorPlatform("", mf);
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkVersion() const
+{
+ return this->DefaultTargetFrameworkVersion;
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkIdentifier() const
+{
+ return this->DefaultTargetFrameworkIdentifier;
+}
+
+cm::optional<std::string> const&
+cmGlobalVisualStudio8Generator::GetTargetFrameworkTargetsVersion() const
+{
+ return this->DefaultTargetFrameworkTargetsVersion;
}
std::string cmGlobalVisualStudio8Generator::GetGenerateStampList()
@@ -245,8 +288,8 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
std::vector<std::string> mapConfig;
const char* dstConfig = i.c_str();
if (target.GetProperty("EXTERNAL_MSPROJECT")) {
- if (cmProp m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
- cmSystemTools::UpperCase(i))) {
+ if (cmValue m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
+ cmSystemTools::UpperCase(i))) {
cmExpandList(*m, mapConfig);
if (!mapConfig.empty()) {
dstConfig = mapConfig[0].c_str();
@@ -287,14 +330,14 @@ bool cmGlobalVisualStudio8Generator::NeedsDeploy(
return false;
}
- if (cmProp prop = target.GetProperty("VS_SOLUTION_DEPLOY")) {
+ if (cmValue prop = target.GetProperty("VS_SOLUTION_DEPLOY")) {
// If set, it dictates behavior
return cmIsOn(
cmGeneratorExpression::Evaluate(*prop, target.LocalGenerator, config));
}
// To be deprecated, disable deployment even if target supports it.
- if (cmProp prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) {
+ if (cmValue prop = target.GetProperty("VS_NO_SOLUTION_DEPLOY")) {
if (cmIsOn(cmGeneratorExpression::Evaluate(*prop, target.LocalGenerator,
config))) {
// If true, always disable deployment
@@ -370,6 +413,7 @@ static cmVS7FlagTable cmVS8ExtraFlagTable[] = {
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
{ "PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
cmVS7FlagTable::UserValueRequired },
+ { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 },
// There is no YX option in the VS8 IDE.
// Exception handling mode. If no entries match, it will be FALSE.
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 96e3553f2..b6ecdf07f 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <cm/optional>
+
#include "cmGlobalVisualStudio71Generator.h"
/** \class cmGlobalVisualStudio8Generator
@@ -24,6 +26,10 @@ public:
bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
+ cm::optional<std::string> const& GetTargetFrameworkVersion() const;
+ cm::optional<std::string> const& GetTargetFrameworkIdentifier() const;
+ cm::optional<std::string> const& GetTargetFrameworkTargetsVersion() const;
+
/**
* Override Configure and Generate to add the build-system check
* target.
@@ -76,4 +82,8 @@ protected:
std::string Name;
std::string WindowsCEVersion;
+
+ cm::optional<std::string> DefaultTargetFrameworkVersion;
+ cm::optional<std::string> DefaultTargetFrameworkIdentifier;
+ cm::optional<std::string> DefaultTargetFrameworkTargetsVersion;
};
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index cdecea03a..f9bd67e08 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -519,7 +519,7 @@ std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(
std::string cmGlobalVisualStudioGenerator::GetStartupProjectName(
cmLocalGenerator const* root) const
{
- cmProp n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT");
+ cmValue n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT");
if (cmNonempty(n)) {
std::string startup = *n;
if (this->FindTarget(startup)) {
@@ -820,7 +820,7 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
// This allows the project to control the language choice in
// a target with none of its own sources, e.g. when also using
// object libraries.
- cmProp linkLang = gt->GetProperty("LINKER_LANGUAGE");
+ cmValue linkLang = gt->GetProperty("LINKER_LANGUAGE");
if (cmNonempty(linkLang)) {
languages.insert(*linkLang);
}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 151f39f12..23c8a0290 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -167,11 +167,6 @@ protected:
void WriteSLNHeader(std::ostream& fout);
- FindMakeProgramStage GetFindMakeProgramStage() const override
- {
- return FindMakeProgramStage::Early;
- }
-
bool ComputeTargetDepends() override;
class VSDependSet : public std::set<std::string>
{
@@ -201,7 +196,7 @@ protected:
private:
virtual std::string GetVSMakeProgram() = 0;
void PrintCompilerAdvice(std::ostream&, std::string const&,
- const char*) const override
+ cmValue) const override
{
}
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index d0ad53e98..b5a6b9fdc 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -401,6 +401,12 @@ cmGlobalVisualStudioVersionedGenerator::cmGlobalVisualStudioVersionedGenerator(
this->DefaultPlatformName = VSHostPlatformName();
this->DefaultPlatformToolsetHostArchitecture = VSHostArchitecture();
}
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS17) {
+ // FIXME: Search for an existing framework? Under '%ProgramFiles(x86)%',
+ // see 'Reference Assemblies\Microsoft\Framework\.NETFramework'.
+ // Use a version installed by VS 2022 without a separate component.
+ this->DefaultTargetFrameworkVersion = "v4.7.2";
+ }
}
bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
@@ -436,6 +442,11 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName(
bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
std::string const& i, cmMakefile* mf)
{
+ if (this->LastGeneratorInstanceString &&
+ i == *(this->LastGeneratorInstanceString)) {
+ return true;
+ }
+
if (!i.empty()) {
if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
std::ostringstream e;
@@ -467,11 +478,16 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance(
// Save the selected instance persistently.
std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
if (vsInstance != genInstance) {
- this->CMakeInstance->AddCacheEntry(
- "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(),
- "Generator instance identifier.", cmStateEnums::INTERNAL);
+ this->CMakeInstance->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", vsInstance,
+ "Generator instance identifier.",
+ cmStateEnums::INTERNAL);
}
+ // The selected instance may have a different MSBuild than previously found.
+ this->MSBuildCommandInitialized = false;
+
+ this->LastGeneratorInstanceString = i;
+
return true;
}
@@ -712,6 +728,17 @@ cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersionDefault(
return std::string();
}
+cm::optional<std::string>
+cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommandEarly(cmMakefile* mf)
+{
+ std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
+ if (!this->SetGeneratorInstance(instance, mf)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return {};
+ }
+ return this->cmGlobalVisualStudio14Generator::FindMSBuildCommandEarly(mf);
+}
+
std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
{
std::string msbuild;
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h
index f07492dff..2aed65b87 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.h
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.h
@@ -8,6 +8,8 @@
#include <memory>
#include <string>
+#include <cm/optional>
+
#include "cmGlobalVisualStudio14Generator.h"
#include "cmVSSetupHelper.h"
@@ -29,6 +31,8 @@ public:
bool GetVSInstance(std::string& dir) const;
+ cm::optional<std::string> FindMSBuildCommandEarly(cmMakefile* mf) override;
+
cm::optional<std::string> GetVSInstanceVersion() const override;
AuxToolset FindAuxToolset(std::string& version,
@@ -72,4 +76,5 @@ private:
class Factory17;
friend class Factory17;
mutable cmVSSetupAPIHelper vsSetupAPIHelper;
+ cm::optional<std::string> LastGeneratorInstanceString;
};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 77403b076..f34ef6270 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -431,14 +431,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(
{
mf->AddDefinition("XCODE", "1");
mf->AddDefinition("XCODE_VERSION", this->VersionString);
- if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
- mf->AddCacheDefinition(
- "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
- "Semicolon separated list of supported configuration types, "
- "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
- "anything else will be ignored.",
- cmStateEnums::STRING);
- }
+ mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
this->ComputeArchitectures(mf);
@@ -948,11 +941,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
gtgt->AddExplicitLanguageFlags(flags, *sf);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = sf->GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = sf->GetProperty(COMPILE_OPTIONS)) {
+ if (cmValue coptions = sf->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
@@ -960,7 +953,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- if (cmProp compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
+ if (cmValue compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
this->AppendDefines(
flagsBuild,
genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS).c_str(),
@@ -981,7 +974,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
// Add per-source include directories.
std::vector<std::string> includes;
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
+ if (cmValue cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
lg->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES),
*sf);
@@ -1013,7 +1006,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
}
// Add user-specified file attributes.
- cmProp extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES");
+ cmValue extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES");
if (extraFileAttributes) {
// Expand the list of attributes.
std::vector<std::string> attributes = cmExpandedList(*extraFileAttributes);
@@ -1104,7 +1097,7 @@ std::string GetSourcecodeValueFromFileExtension(
} else if (ext == "h") {
sourcecode += ".c.h";
} else if (ext == "hxx" || ext == "hpp" || ext == "txx" || ext == "pch" ||
- ext == "hh") {
+ ext == "hh" || ext == "inl") {
sourcecode += ".cpp.h";
} else if (ext == "png" || ext == "gif" || ext == "jpg") {
keepLastKnownFileType = true;
@@ -1201,9 +1194,9 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
bool useLastKnownFileType = false;
std::string fileType;
if (sf) {
- if (cmProp e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
+ if (cmValue e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
fileType = *e;
- } else if (cmProp l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) {
+ } else if (cmValue l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) {
useLastKnownFileType = true;
fileType = *l;
}
@@ -1674,7 +1667,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
fout << "\n";
}
if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) {
- sf->SetProperty("LANGUAGE", llang.c_str());
+ sf->SetProperty("LANGUAGE", llang);
gtgt->AddSource(fname);
}
}
@@ -1763,9 +1756,6 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (sourceFile->GetCustomCommand() &&
visited.insert(sourceFile).second) {
commands.push_back(*sourceFile->GetCustomCommand());
- if (this->XcodeBuildSystem >= BuildSystem::Twelve) {
- this->CustomCommandRoots[sourceFile].insert(gtgt);
- }
}
}
// create custom commands phase
@@ -2420,7 +2410,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->CurrentLocalGenerator->GetStaticLibraryFlags(
extraLinkOptions, configName, llang, gtgt);
} else {
- cmProp targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
+ cmValue targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions,
*targetLinkFlags);
@@ -2428,7 +2418,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (!configName.empty()) {
std::string linkFlagsVar =
cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName));
- if (cmProp linkFlags = gtgt->GetProperty(linkFlagsVar)) {
+ if (cmValue linkFlags = gtgt->GetProperty(linkFlagsVar)) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, *linkFlags);
}
}
@@ -2465,8 +2455,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string pnsuffix;
gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
- cmProp version = gtgt->GetProperty("VERSION");
- cmProp soversion = gtgt->GetProperty("SOVERSION");
+ cmValue version = gtgt->GetProperty("VERSION");
+ cmValue soversion = gtgt->GetProperty("SOVERSION");
if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) {
version = nullptr;
soversion = nullptr;
@@ -2530,7 +2520,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string fw_version = gtgt->GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(fw_version));
- cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
@@ -2571,7 +2561,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
extraLinkOptions += " ";
extraLinkOptions += createFlags;
}
- cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
@@ -2605,7 +2595,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string fw_version = gtgt->GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION",
this->CreateString(fw_version));
- cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
@@ -2644,7 +2634,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// Handle bundles and normal executables separately.
if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
- cmProp ext = gtgt->GetProperty("BUNDLE_EXTENSION");
+ cmValue ext = gtgt->GetProperty("BUNDLE_EXTENSION");
if (ext) {
buildSettings->AddAttribute("WRAPPER_EXTENSION",
this->CreateString(*ext));
@@ -3090,7 +3080,7 @@ const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(
const char* cmGlobalXCodeGenerator::GetTargetFileType(
cmGeneratorTarget* target)
{
- if (cmProp e = target->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
+ if (cmValue e = target->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) {
return e->c_str();
}
@@ -3123,7 +3113,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
const char* cmGlobalXCodeGenerator::GetTargetProductType(
cmGeneratorTarget* target)
{
- if (cmProp e = target->GetProperty("XCODE_PRODUCT_TYPE")) {
+ if (cmValue e = target->GetProperty("XCODE_PRODUCT_TYPE")) {
return e->c_str();
}
@@ -3242,15 +3232,14 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
const std::string& id)
{
std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
- cmProp storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName);
+ cmValue storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName);
if (storedGUID) {
return *storedGUID;
}
- this->CMakeInstance->AddCacheEntry(guidStoreName, id.c_str(),
- "Stored Xcode object GUID",
- cmStateEnums::INTERNAL);
+ this->CMakeInstance->AddCacheEntry(
+ guidStoreName, id, "Stored Xcode object GUID", cmStateEnums::INTERNAL);
return id;
}
@@ -3419,7 +3408,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
std::map<std::string, std::vector<std::string>> targetProductNameMap;
bool useLinkPhase = false;
bool forceLinkPhase = false;
- cmProp prop =
+ cmValue prop =
target->GetTarget()->GetProperty("XCODE_LINK_BUILD_PHASE_MODE");
if (prop) {
if (*prop == "BUILT_ONLY") {
@@ -3792,7 +3781,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
return;
}
- cmProp files = gt->GetProperty(embedPropertyName);
+ cmValue files = gt->GetProperty(embedPropertyName);
if (!files) {
return;
}
@@ -3807,7 +3796,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
this->CreateString(dstSubfolderSpec));
copyFilesBuildPhase->AddAttribute(
"name", this->CreateString(copyFilesBuildPhaseName));
- if (cmProp fwEmbedPath =
+ if (cmValue fwEmbedPath =
gt->GetProperty(cmStrCat(embedPropertyName, "_PATH"))) {
copyFilesBuildPhase->AddAttribute("dstPath",
this->CreateString(*fwEmbedPath));
@@ -3817,7 +3806,7 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- // Collect all embedded frameworks and add them to build phase
+ // Collect all embedded frameworks and dylibs and add them to build phase
std::vector<std::string> relFiles = cmExpandedList(*files);
for (std::string const& relFile : relFiles) {
cmXCodeObject* buildFile{ nullptr };
@@ -3847,7 +3836,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
} else {
buildFile = it->second;
}
- } else if (cmSystemTools::IsPathToFramework(relFile)) {
+ } else if (cmSystemTools::IsPathToFramework(relFile) ||
+ cmSystemTools::IsPathToMacOSSharedLibrary(relFile)) {
// This is a regular string path - create file reference
auto it = this->EmbeddedLibRefs.find(relFile);
if (it == this->EmbeddedLibRefs.end()) {
@@ -3913,6 +3903,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
{
static const auto dstSubfolderSpec = "10";
+ // Despite the name, by default Xcode uses "Embed Frameworks" build phase for
+ // both frameworks and dynamic libraries
this->AddEmbeddedObjects(target, "Embed Frameworks",
"XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec,
NoActionOnCopyByDefault);
@@ -4191,8 +4183,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateString(defaultConfigName));
cmXCodeObject* buildSettings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- cmProp sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
- cmProp deploymentTarget =
+ cmValue sysroot = this->CurrentMakefile->GetDefinition("CMAKE_OSX_SYSROOT");
+ cmValue deploymentTarget =
this->CurrentMakefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
if (sysroot) {
buildSettings->AddAttribute("SDKROOT", this->CreateString(*sysroot));
@@ -4225,7 +4217,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
}
if (this->GetLanguageEnabled("Swift")) {
std::string swiftVersion;
- if (cmProp vers = this->CurrentMakefile->GetDefinition(
+ if (cmValue vers = this->CurrentMakefile->GetDefinition(
"CMAKE_Swift_LANGUAGE_VERSION")) {
swiftVersion = *vers;
} else if (this->XcodeVersion >= 102) {
@@ -4348,7 +4340,7 @@ std::string cmGlobalXCodeGenerator::GetObjectsDirectory(
void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
{
this->Architectures.clear();
- cmProp sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
+ cmValue sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
if (sysroot) {
mf->GetDefExpandList("CMAKE_OSX_ARCHITECTURES", this->Architectures);
}
@@ -4361,7 +4353,7 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
// With no ARCHS we use ONLY_ACTIVE_ARCH and possibly a
// platform-specific default ARCHS placeholder value.
// Look up the arch that Xcode chooses in this case.
- if (cmProp arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) {
+ if (cmValue arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) {
this->ObjectDirArchDefault = *arch;
// We expect only one arch but choose the first just in case.
std::string::size_type pos = this->ObjectDirArchDefault.find(';');
@@ -4555,7 +4547,7 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
continue;
}
- cmProp testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE");
+ cmValue testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE");
if (!testee) {
continue;
}
@@ -4738,7 +4730,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags(
{
if (!varNameLang.empty()) {
std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix);
- if (cmProp varValue = this->CurrentMakefile->GetDefinition(varName)) {
+ if (cmValue varValue = this->CurrentMakefile->GetDefinition(varName)) {
if (!varValue->empty()) {
return *varValue;
}
@@ -4860,7 +4852,7 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
{
- cmProp epnValue = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
+ cmValue epnValue = this->GetCMakeInstance()->GetState()->GetGlobalProperty(
"XCODE_EMIT_EFFECTIVE_PLATFORM_NAME");
if (!epnValue) {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 1e1b344c9..4d7ee9010 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -138,11 +138,6 @@ protected:
void AddExtraIDETargets() override;
void Generate() override;
- FindMakeProgramStage GetFindMakeProgramStage() const override
- {
- return FindMakeProgramStage::Early;
- }
-
private:
enum EmbedActionFlags
{
@@ -327,7 +322,7 @@ private:
bool XcodeBuildCommandInitialized;
void PrintCompilerAdvice(std::ostream&, std::string const&,
- const char*) const override
+ cmValue) const override
{
}
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 122bda52d..ab18e2a66 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -17,11 +17,11 @@
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -232,7 +232,7 @@ void cmGraphVizWriter::ReadSettings(
#define set_if_set(var, cmakeDefinition) \
do { \
- cmProp value = mf.GetDefinition(cmakeDefinition); \
+ cmValue value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
(var) = *value; \
} \
@@ -244,7 +244,7 @@ void cmGraphVizWriter::ReadSettings(
#define set_bool_if_set(var, cmakeDefinition) \
do { \
- cmProp value = mf.GetDefinition(cmakeDefinition); \
+ cmValue value = mf.GetDefinition(cmakeDefinition); \
if (value) { \
(var) = cmIsOn(*value); \
} \
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index ce1f030be..7b0320c1f 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -120,6 +120,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n";
modal = "should";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index b408f7210..23427a1a5 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -13,6 +13,7 @@
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
static void GetIncludes(cmMakefile& mf, const std::string& arg,
std::vector<std::string>& incs);
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index 5b532ce0f..c8b4a39e7 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -77,9 +77,8 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args,
if (!customGuid.empty()) {
std::string guidVariable = utility_name + "_GUID_CMAKE";
- mf.GetCMakeInstance()->AddCacheEntry(guidVariable, customGuid.c_str(),
- "Stored GUID",
- cmStateEnums::INTERNAL);
+ mf.GetCMakeInstance()->AddCacheEntry(
+ guidVariable, customGuid, "Stored GUID", cmStateEnums::INTERNAL);
}
// Create a target instance for this utility.
diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx
index aefd0985f..e0a6958dd 100644
--- a/Source/cmIncludeGuardCommand.cxx
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -7,6 +7,7 @@
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
diff --git a/Source/cmIncludeRegularExpressionCommand.cxx b/Source/cmIncludeRegularExpressionCommand.cxx
index 655ebd6e4..cdcc7df71 100644
--- a/Source/cmIncludeRegularExpressionCommand.cxx
+++ b/Source/cmIncludeRegularExpressionCommand.cxx
@@ -14,7 +14,7 @@ bool cmIncludeRegularExpressionCommand(std::vector<std::string> const& args,
}
cmMakefile& mf = status.GetMakefile();
- mf.SetIncludeRegularExpression(args[0].c_str());
+ mf.SetIncludeRegularExpression(args[0]);
if (args.size() > 1) {
mf.SetComplainRegularExpression(args[1]);
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 79109b508..eaf88f64a 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -35,7 +35,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
+#include "cmRange.h"
#include "cmRuntimeDependencyArchive.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -43,6 +43,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
+#include "cmValue.h"
namespace {
@@ -681,8 +682,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
te->LibraryGenerator = libraryGenerator.get();
te->RuntimeGenerator = runtimeGenerator.get();
te->ObjectsGenerator = objectGenerator.get();
- te->InterfaceIncludeDirectories =
- cmJoin(includesArgs.GetIncludeDirs(), ";");
+ target.AddInstallIncludeDirectories(
+ cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
helper.Makefile->GetGlobalGenerator()
->GetExportSets()[exports]
@@ -925,7 +926,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
- cmProp files = target.GetProperty("PRIVATE_HEADER");
+ cmValue files = target.GetProperty("PRIVATE_HEADER");
if (cmNonempty(files)) {
std::vector<std::string> relFiles = cmExpandedList(*files);
std::vector<std::string> absFiles;
@@ -1390,6 +1391,7 @@ bool HandleFilesMode(std::vector<std::string> const& args,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n";
modal = "should";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
@@ -1397,6 +1399,7 @@ bool HandleFilesMode(std::vector<std::string> const& args,
case cmPolicies::NEW:
modal = "may";
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (modal) {
e << "The file\n " << file
diff --git a/Source/cmInstallMode.h b/Source/cmInstallMode.h
new file mode 100644
index 000000000..5343d34a4
--- /dev/null
+++ b/Source/cmInstallMode.h
@@ -0,0 +1,17 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+/**
+ * Enumerate types known to file(INSTALL).
+ */
+enum class cmInstallMode
+{
+ COPY,
+ ABS_SYMLINK,
+ ABS_SYMLINK_OR_COPY,
+ REL_SYMLINK,
+ REL_SYMLINK_OR_COPY,
+ SYMLINK,
+ SYMLINK_OR_COPY
+};
diff --git a/Source/cmInstallSubdirectoryGenerator.cxx b/Source/cmInstallSubdirectoryGenerator.cxx
index 794694ea3..0a8e065b5 100644
--- a/Source/cmInstallSubdirectoryGenerator.cxx
+++ b/Source/cmInstallSubdirectoryGenerator.cxx
@@ -57,6 +57,7 @@ void cmInstallSubdirectoryGenerator::GenerateScript(std::ostream& os)
this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0082);
switch (status) {
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is handled in cmLocalGenerator::GenerateInstallRules()
break;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 35165cf72..ae11afca9 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -2,11 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallTargetGenerator.h"
+#include <algorithm>
#include <cassert>
#include <map>
#include <set>
#include <sstream>
#include <utility>
+#include <vector>
#include "cmComputeLinkInformation.h"
#include "cmGeneratorExpression.h"
@@ -18,11 +20,11 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -208,7 +210,7 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
// Get App Bundle Extension
std::string ext;
- if (cmProp p = this->Target->GetProperty("BUNDLE_EXTENSION")) {
+ if (cmValue p = this->Target->GetProperty("BUNDLE_EXTENSION")) {
ext = *p;
} else {
ext = "app";
@@ -680,33 +682,52 @@ void cmInstallTargetGenerator::AddChrpathPatchRule(
" this limitation.";
mf->IssueMessage(MessageType::WARNING, msg.str());
} else {
- // Note: These paths are kept unique to avoid
- // install_name_tool corruption.
- std::set<std::string> runpaths;
- for (std::string const& i : oldRuntimeDirs) {
- std::string runpath =
- mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
-
- if (runpaths.find(runpath) == runpaths.end()) {
- runpaths.insert(runpath);
- os << indent << "execute_process(COMMAND " << installNameTool
- << "\n";
- os << indent << " -delete_rpath \"" << runpath << "\"\n";
- os << indent << " \"" << toDestDirPath << "\")\n";
+ // To be consistent with older versions, runpath changes must be ordered,
+ // deleted first, then added, *and* the same path must only appear once.
+ std::map<std::string, std::string> runpath_change;
+ std::vector<std::string> ordered;
+ for (std::string const& dir : oldRuntimeDirs) {
+ // Normalize path and add to map of changes to make
+ auto iter_inserted = runpath_change.insert(
+ { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config),
+ "delete" });
+ if (iter_inserted.second) {
+ // Add path to ordered list of changes
+ ordered.push_back(iter_inserted.first->first);
}
}
- runpaths.clear();
- for (std::string const& i : newRuntimeDirs) {
- std::string runpath =
- mf->GetGlobalGenerator()->ExpandCFGIntDir(i, config);
+ for (std::string const& dir : newRuntimeDirs) {
+ // Normalize path and add to map of changes to make
+ auto iter_inserted = runpath_change.insert(
+ { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config), "add" });
+ if (iter_inserted.second) {
+ // Add path to ordered list of changes
+ ordered.push_back(iter_inserted.first->first);
+ } else if (iter_inserted.first->second != "add") {
+ // Rpath was requested to be deleted and then later re-added. Drop it
+ // from the list by marking as an empty value.
+ iter_inserted.first->second.clear();
+ }
+ }
- if (runpaths.find(runpath) == runpaths.end()) {
- os << indent << "execute_process(COMMAND " << installNameTool
- << "\n";
- os << indent << " -add_rpath \"" << runpath << "\"\n";
- os << indent << " \"" << toDestDirPath << "\")\n";
+ // Remove rpaths that are unchanged (value was set to empty)
+ ordered.erase(
+ std::remove_if(ordered.begin(), ordered.end(),
+ [&runpath_change](const std::string& runpath) {
+ return runpath_change.find(runpath)->second.empty();
+ }),
+ ordered.end());
+
+ if (!ordered.empty()) {
+ os << indent << "execute_process(COMMAND " << installNameTool << "\n";
+ for (std::string const& runpath : ordered) {
+ // Either 'add_rpath' or 'delete_rpath' since we've removed empty
+ // entries
+ os << indent << " -" << runpath_change.find(runpath)->second
+ << "_rpath \"" << runpath << "\"\n";
}
+ os << indent << " \"" << toDestDirPath << "\")\n";
}
}
} else {
@@ -825,7 +846,7 @@ void cmInstallTargetGenerator::AddUniversalInstallRule(
return;
}
- cmProp xcodeVersion = mf->GetDefinition("XCODE_VERSION");
+ cmValue xcodeVersion = mf->GetDefinition("XCODE_VERSION");
if (!xcodeVersion ||
cmSystemTools::VersionCompareGreater("6", *xcodeVersion)) {
return;
diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx
index 32395d10e..0974eea56 100644
--- a/Source/cmInstalledFile.cxx
+++ b/Source/cmInstalledFile.cxx
@@ -8,6 +8,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
cmInstalledFile::cmInstalledFile() = default;
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 29140462a..1ec071b75 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -62,7 +62,7 @@ static void AddLinkDir(cmMakefile& mf, std::string const& dir,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015);
mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
- break;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior does not convert
break;
diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx
index 4e50d7097..62e7ef425 100644
--- a/Source/cmLinkItem.cxx
+++ b/Source/cmLinkItem.cxx
@@ -32,7 +32,11 @@ bool operator<(cmLinkItem const& l, cmLinkItem const& r)
{
// Order among targets.
if (l.Target && r.Target) {
- return l.Target < r.Target;
+ if (l.Target != r.Target) {
+ return l.Target < r.Target;
+ }
+ // Order identical targets via cross-config.
+ return l.Cross < r.Cross;
}
// Order targets before strings.
if (l.Target) {
@@ -42,10 +46,10 @@ bool operator<(cmLinkItem const& l, cmLinkItem const& r)
return false;
}
// Order among strings.
- if (l.String < r.String) {
- return true;
+ if (l.String != r.String) {
+ return l.String < r.String;
}
- // Order among cross-config.
+ // Order identical strings via cross-config.
return l.Cross < r.Cross;
}
diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx
index 2ffff96b9..43f161be4 100644
--- a/Source/cmLinkLineDeviceComputer.cxx
+++ b/Source/cmLinkLineDeviceComputer.cxx
@@ -16,11 +16,11 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
class cmOutputConverter;
@@ -177,7 +177,7 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg,
return false;
}
- if (cmProp resolveDeviceSymbols =
+ if (cmValue resolveDeviceSymbols =
target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) {
// If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need
// to honor the value no matter what it is.
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 09cd88e08..7d42fc827 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -25,12 +25,12 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmStringReplaceHelper.h"
#include "cmSubcommandTable.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
@@ -46,7 +46,7 @@ bool GetIndexArg(const std::string& arg, int* idx, cmMakefile& mf)
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121),
" Invalid list index \"", arg, "\".");
mf.IssueMessage(MessageType::AUTHOR_WARNING, warn);
- break;
+ CM_FALLTHROUGH;
}
case cmPolicies::OLD:
// OLD behavior is to allow compatibility, so just ignore the
@@ -79,7 +79,7 @@ bool GetListString(std::string& listString, const std::string& var,
const cmMakefile& makefile)
{
// get the old value
- cmProp cacheValue = makefile.GetDefinition(var);
+ cmValue cacheValue = makefile.GetDefinition(var);
if (!cacheValue) {
return false;
}
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 4f7c95944..2e444f229 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -548,7 +548,7 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const
}
cmListFileContext lfc = this->TopEntry->Context;
cmStateSnapshot bottom = this->GetBottom();
- if (!bottom.GetState()->GetIsInTryCompile()) {
+ if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
@@ -579,7 +579,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
out << "Call Stack (most recent call first):\n";
}
cmListFileContext lfc = cur->Context;
- if (!bottom.GetState()->GetIsInTryCompile()) {
+ if (bottom.GetState()->GetProjectKind() == cmState::ProjectKind::Normal) {
lfc.FilePath = cmSystemTools::RelativeIfUnder(
bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
}
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 211525a26..eca7a9eb6 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -8,11 +8,11 @@
#include "cmGeneratorTarget.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
class cmGlobalGenerator;
@@ -82,7 +82,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
// If there is a separate module path flag then duplicate the
// include path with it. This compiler does not search the include
// path for modules.
- if (cmProp modpath_flag =
+ if (cmValue modpath_flag =
this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG")) {
std::vector<std::string> includes;
this->GetIncludeDirectories(includes, target, "C", config);
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b282de98..fc5e6e5f1 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -37,7 +37,6 @@
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
@@ -50,6 +49,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTestGenerator.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -107,10 +107,9 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
{
std::vector<std::string> cpath;
cmSystemTools::GetPath(cpath, "CPATH");
- for (std::string& cp : cpath) {
+ for (std::string const& cp : cpath) {
if (cmSystemTools::FileIsFullPath(cp)) {
- cp = cmSystemTools::CollapseFullPath(cp);
- this->EnvCPATH.emplace(std::move(cp));
+ this->EnvCPATH.emplace_back(cmSystemTools::CollapseFullPath(cp));
}
}
}
@@ -118,21 +117,21 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
std::vector<std::string> enabledLanguages =
this->GetState()->GetEnabledLanguages();
- if (cmProp sysrootCompile =
+ if (cmValue sysrootCompile =
this->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
this->CompilerSysroot = *sysrootCompile;
} else {
this->CompilerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
- if (cmProp sysrootLink =
+ if (cmValue sysrootLink =
this->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
this->LinkerSysroot = *sysrootLink;
} else {
this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
- if (cmProp appleArchSysroots =
+ if (cmValue appleArchSysroots =
this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) {
std::string const& appleArchs =
this->Makefile->GetSafeDefinition("CMAKE_OSX_ARCHITECTURES");
@@ -222,7 +221,7 @@ void cmLocalGenerator::ComputeObjectMaxPath()
#else
this->ObjectPathMax = 1000;
#endif
- cmProp plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX");
+ cmValue plen = this->Makefile->GetDefinition("CMAKE_OBJECT_PATH_MAX");
if (cmNonempty(plen)) {
unsigned int pmax;
if (sscanf(plen->c_str(), "%u", &pmax) == 1) {
@@ -330,12 +329,12 @@ void cmLocalGenerator::GenerateTestFiles()
fout << "set(CTEST_RESOURCE_SPEC_FILE \"" << resourceSpecFile << "\")\n";
}
- cmProp testIncludeFile = this->Makefile->GetProperty("TEST_INCLUDE_FILE");
+ cmValue testIncludeFile = this->Makefile->GetProperty("TEST_INCLUDE_FILE");
if (testIncludeFile) {
fout << "include(\"" << *testIncludeFile << "\")\n";
}
- cmProp testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES");
+ cmValue testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES");
if (testIncludeFiles) {
std::vector<std::string> includesList = cmExpandedList(*testIncludeFiles);
for (std::string const& i : includesList) {
@@ -359,9 +358,9 @@ void cmLocalGenerator::GenerateTestFiles()
}
// Add directory labels property
- cmProp directoryLabels =
+ cmValue directoryLabels =
this->Makefile->GetDefinition("CMAKE_DIRECTORY_LABELS");
- cmProp labels = this->Makefile->GetProperty("LABELS");
+ cmValue labels = this->Makefile->GetProperty("LABELS");
if (labels || directoryLabels) {
fout << "set_directory_properties(PROPERTIES LABELS ";
@@ -426,27 +425,26 @@ void cmLocalGenerator::ProcessEvaluationFiles(
void cmLocalGenerator::GenerateInstallRules()
{
// Compute the install prefix.
- const char* prefix =
- cmToCStr(this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"));
+ cmValue installPrefix =
+ this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX");
+ std::string prefix = installPrefix;
#if defined(_WIN32) && !defined(__CYGWIN__)
- std::string prefix_win32;
- if (!prefix) {
- if (!cmSystemTools::GetEnv("SystemDrive", prefix_win32)) {
- prefix_win32 = "C:";
+ if (!installPrefix) {
+ if (!cmSystemTools::GetEnv("SystemDrive", prefix)) {
+ prefix = "C:";
}
- cmProp project_name = this->Makefile->GetDefinition("PROJECT_NAME");
+ cmValue project_name = this->Makefile->GetDefinition("PROJECT_NAME");
if (cmNonempty(project_name)) {
- prefix_win32 += "/Program Files/";
- prefix_win32 += *project_name;
+ prefix += "/Program Files/";
+ prefix += *project_name;
} else {
- prefix_win32 += "/InstalledCMakeProject";
+ prefix += "/InstalledCMakeProject";
}
- prefix = prefix_win32.c_str();
}
#elif defined(__HAIKU__)
char dir[B_PATH_NAME_LENGTH];
- if (!prefix) {
+ if (!installPrefix) {
if (find_directory(B_SYSTEM_DIRECTORY, -1, false, dir, sizeof(dir)) ==
B_OK) {
prefix = dir;
@@ -455,13 +453,13 @@ void cmLocalGenerator::GenerateInstallRules()
}
}
#else
- if (!prefix) {
+ if (!installPrefix) {
prefix = "/usr/local";
}
#endif
- if (cmProp stagingPrefix =
+ if (cmValue stagingPrefix =
this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) {
- prefix = stagingPrefix->c_str();
+ prefix = *stagingPrefix;
}
// Compute the set of configurations.
@@ -541,7 +539,7 @@ void cmLocalGenerator::GenerateInstallRules()
/* clang-format on */
// Copy user-specified install options to the install code.
- if (cmProp so_no_exe =
+ if (cmValue so_no_exe =
this->Makefile->GetDefinition("CMAKE_INSTALL_SO_NO_EXE")) {
/* clang-format off */
fout <<
@@ -554,7 +552,7 @@ void cmLocalGenerator::GenerateInstallRules()
}
// Copy cmake cross compile state to install code.
- if (cmProp crosscompiling =
+ if (cmValue crosscompiling =
this->Makefile->GetDefinition("CMAKE_CROSSCOMPILING")) {
/* clang-format off */
fout <<
@@ -567,7 +565,7 @@ void cmLocalGenerator::GenerateInstallRules()
}
// Write default directory permissions.
- if (cmProp defaultDirPermissions = this->Makefile->GetDefinition(
+ if (cmValue defaultDirPermissions = this->Makefile->GetDefinition(
"CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) {
/* clang-format off */
fout <<
@@ -583,7 +581,7 @@ void cmLocalGenerator::GenerateInstallRules()
// Write out CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM so that
// installed code that uses `file(GET_RUNTIME_DEPENDENCIES)`
// has same platform variable as when running cmake
- if (cmProp platform = this->Makefile->GetDefinition(
+ if (cmValue platform = this->Makefile->GetDefinition(
"CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM")) {
/* clang-format off */
fout <<
@@ -599,7 +597,7 @@ void cmLocalGenerator::GenerateInstallRules()
// Write out CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL so that
// installed code that uses `file(GET_RUNTIME_DEPENDENCIES)`
// has same tool selected as when running cmake
- if (cmProp command =
+ if (cmValue command =
this->Makefile->GetDefinition("CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL")) {
/* clang-format off */
fout <<
@@ -615,7 +613,7 @@ void cmLocalGenerator::GenerateInstallRules()
// Write out CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND so that
// installed code that uses `file(GET_RUNTIME_DEPENDENCIES)`
// has same path to the tool as when running cmake
- if (cmProp command = this->Makefile->GetDefinition(
+ if (cmValue command = this->Makefile->GetDefinition(
"CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND")) {
/* clang-format off */
fout <<
@@ -633,7 +631,7 @@ void cmLocalGenerator::GenerateInstallRules()
// CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND has consistent
// logic to fallback to CMAKE_OBJDUMP when `objdump` is
// not on the path
- if (cmProp command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) {
+ if (cmValue command = this->Makefile->GetDefinition("CMAKE_OBJDUMP")) {
/* clang-format off */
fout <<
"# Set default install directory permissions.\n"
@@ -826,8 +824,8 @@ cmStateSnapshot cmLocalGenerator::GetStateSnapshot() const
return this->Makefile->GetStateSnapshot();
}
-cmProp cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
- const std::string& prop)
+cmValue cmLocalGenerator::GetRuleLauncher(cmGeneratorTarget* target,
+ const std::string& prop)
{
if (target) {
return target->GetProperty(prop);
@@ -859,36 +857,39 @@ std::string cmLocalGenerator::GetIncludeFlags(
std::string const& includeFlag =
this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang));
- const char* sep = cmToCStr(
- this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang)));
bool quotePaths = false;
if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) {
quotePaths = true;
}
+ std::string sep = " ";
bool repeatFlag = true;
// should the include flag be repeated like ie. -IA -IB
- if (!sep) {
- sep = " ";
- } else {
+ if (cmValue incSep = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang))) {
// if there is a separator then the flag is not repeated but is only
// given once i.e. -classpath a:b:c
+ sep = incSep;
repeatFlag = false;
}
// Support special system include flag if it is available and the
// normal flag is repeated for each directory.
- cmProp sysIncludeFlag = nullptr;
+ cmValue sysIncludeFlag = nullptr;
+ cmValue sysIncludeFlagWarning = nullptr;
if (repeatFlag) {
sysIncludeFlag = this->Makefile->GetDefinition(
cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang));
+ sysIncludeFlagWarning = this->Makefile->GetDefinition(
+ cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", lang, "_WARNING"));
}
- cmProp fwSearchFlag = this->Makefile->GetDefinition(
+ cmValue fwSearchFlag = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG"));
- cmProp sysFwSearchFlag = this->Makefile->GetDefinition(
+ cmValue sysFwSearchFlag = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG"));
bool flagUsed = false;
+ bool sysIncludeFlagUsed = false;
std::set<std::string> emitted;
#ifdef __APPLE__
emitted.insert("/System/Library/Frameworks");
@@ -915,6 +916,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
if (sysIncludeFlag && target &&
target->IsSystemIncludeDirectory(i, config, lang)) {
includeFlags << *sysIncludeFlag;
+ sysIncludeFlagUsed = true;
} else {
includeFlags << includeFlag;
}
@@ -931,6 +933,9 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
includeFlags << sep;
}
+ if (sysIncludeFlagUsed && sysIncludeFlagWarning) {
+ includeFlags << *sysIncludeFlagWarning;
+ }
std::string flags = includeFlags.str();
// remove trailing separators
if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) {
@@ -956,10 +961,10 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
{
std::string langFlagRegexVar = cmStrCat("CMAKE_", lang, "_FLAG_REGEX");
- if (cmProp langFlagRegexStr =
+ if (cmValue langFlagRegexStr =
this->Makefile->GetDefinition(langFlagRegexVar)) {
// Filter flags acceptable to this language.
- if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) {
+ if (cmValue targetFlags = target->GetProperty("COMPILE_FLAGS")) {
std::vector<std::string> opts;
cmSystemTools::ParseWindowsCommandLine(targetFlags->c_str(), opts);
// Re-escape these flags since COMPILE_FLAGS were already parsed
@@ -977,7 +982,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
langFlagRegexStr->c_str());
} else {
// Use all flags.
- if (cmProp targetFlags = target->GetProperty("COMPILE_FLAGS")) {
+ if (cmValue targetFlags = target->GetProperty("COMPILE_FLAGS")) {
// COMPILE_FLAGS are not escaped for historical reasons.
std::string compileFlags;
this->AppendFlags(compileFlags, *targetFlags);
@@ -993,7 +998,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
cmStandardLevelResolver standardResolver(this->Makefile);
for (auto const& it : target->GetMaxLanguageStandards()) {
- cmProp standard = target->GetLanguageStandard(it.first, config);
+ cmValue standard = target->GetLanguageStandard(it.first, config);
if (!standard) {
continue;
}
@@ -1024,7 +1029,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
// Add compile flag for the MSVC compiler only.
cmMakefile* mf = this->GetMakefile();
- if (cmProp jmc =
+ if (cmValue jmc =
mf->GetDefinition("CMAKE_" + lang + "_COMPILE_OPTIONS_JMC")) {
// Handle Just My Code debugging flags, /JMC.
@@ -1033,7 +1038,7 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags,
cmGeneratorTarget::ManagedType::Managed) {
// add /JMC flags if target property VS_JUST_MY_CODE_DEBUGGING is set
// to ON
- if (cmProp jmcExprGen =
+ if (cmValue jmcExprGen =
target->GetProperty("VS_JUST_MY_CODE_DEBUGGING")) {
std::string isJMCEnabled =
cmGeneratorExpression::Evaluate(*jmcExprGen, this, config);
@@ -1239,19 +1244,31 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit(
}
}
+ bool const isCorCxx = (lang == "C" || lang == "CXX");
+
+ // Resolve symlinks in CPATH for comparison with resolved include paths.
+ // We do this here instead of when EnvCPATH is populated in case symlinks
+ // on disk have changed in the meantime.
+ std::set<std::string> resolvedEnvCPATH;
+ if (isCorCxx) {
+ for (std::string const& i : this->EnvCPATH) {
+ resolvedEnvCPATH.emplace(this->GlobalGenerator->GetRealPath(i));
+ }
+ }
+
// Checks if this is not an excluded (implicit) include directory.
- auto notExcluded = [this, &implicitSet, &implicitExclude,
- &lang](std::string const& dir) {
- return (
- // Do not exclude directories that are not in an excluded set.
- ((!cm::contains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) &&
- (!cm::contains(implicitExclude, dir)))
+ auto notExcluded = [this, &implicitSet, &implicitExclude, &resolvedEnvCPATH,
+ isCorCxx](std::string const& dir) -> bool {
+ std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir);
+ return
+ // Do not exclude directories that are not in any excluded set.
+ !(cm::contains(implicitSet, real_dir) ||
+ cm::contains(implicitExclude, dir))
// Do not exclude entries of the CPATH environment variable even though
// they are implicitly searched by the compiler. They are meant to be
// user-specified directories that can be re-ordered or converted to
// -isystem without breaking real compiler builtin headers.
- ||
- ((lang == "C" || lang == "CXX") && cm::contains(this->EnvCPATH, dir)));
+ || (isCorCxx && cm::contains(resolvedEnvCPATH, real_dir));
};
// Get the target-specific include directories.
@@ -1480,7 +1497,7 @@ void cmLocalGenerator::GetTargetFlags(
}
}
- cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS");
+ cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
sharedLibFlags += *targetLinkFlags;
sharedLibFlags += " ";
@@ -1560,7 +1577,7 @@ void cmLocalGenerator::GetTargetFlags(
exeFlags += " ";
}
- cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS");
+ cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
exeFlags += *targetLinkFlags;
exeFlags += " ";
@@ -1656,7 +1673,7 @@ static std::string GetFrameworkFlags(const std::string& lang,
}
std::string fwSearchFlagVar = "CMAKE_" + lang + "_FRAMEWORK_SEARCH_FLAG";
- cmProp fwSearchFlag = mf->GetDefinition(fwSearchFlagVar);
+ cmValue fwSearchFlag = mf->GetDefinition(fwSearchFlagVar);
if (!cmNonempty(fwSearchFlag)) {
return std::string();
}
@@ -1765,7 +1782,7 @@ void cmLocalGenerator::OutputLinkLibraries(
std::string linkLanguage = cli.GetLinkLanguage();
std::string libPathFlag;
- if (cmProp value = this->Makefile->GetDefinition(
+ if (cmValue value = this->Makefile->GetDefinition(
"CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_FLAG")) {
libPathFlag = *value;
} else {
@@ -1774,7 +1791,7 @@ void cmLocalGenerator::OutputLinkLibraries(
}
std::string libPathTerminator;
- if (cmProp value = this->Makefile->GetDefinition(
+ if (cmValue value = this->Makefile->GetDefinition(
"CMAKE_" + cli.GetLinkLanguage() + "_LIBRARY_PATH_TERMINATOR")) {
libPathTerminator = *value;
} else {
@@ -1850,17 +1867,17 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065(
}
bool cmLocalGenerator::AllAppleArchSysrootsAreTheSame(
- const std::vector<std::string>& archs, const char* sysroot)
+ const std::vector<std::string>& archs, cmValue sysroot)
{
if (!sysroot) {
return false;
}
return std::all_of(archs.begin(), archs.end(),
- [this, &sysroot](std::string const& arch) -> bool {
+ [this, sysroot](std::string const& arch) -> bool {
std::string const& archSysroot =
this->AppleArchSysroots[arch];
- return cmIsOff(archSysroot) || archSysroot == sysroot;
+ return cmIsOff(archSysroot) || sysroot == archSysroot;
});
}
@@ -1885,15 +1902,15 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
}
}
- cmProp sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
+ cmValue sysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
if (sysroot && *sysroot == "/") {
sysroot = nullptr;
}
std::string sysrootFlagVar = "CMAKE_" + lang + "_SYSROOT_FLAG";
- cmProp sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
+ cmValue sysrootFlag = this->Makefile->GetDefinition(sysrootFlagVar);
if (cmNonempty(sysrootFlag)) {
if (!this->AppleArchSysroots.empty() &&
- !this->AllAppleArchSysrootsAreTheSame(archs, cmToCStr(sysroot))) {
+ !this->AllAppleArchSysrootsAreTheSame(archs, sysroot)) {
for (std::string const& arch : archs) {
std::string const& archSysroot = this->AppleArchSysroots[arch];
if (cmIsOff(archSysroot)) {
@@ -1914,11 +1931,11 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
}
}
- cmProp deploymentTarget =
+ cmValue deploymentTarget =
this->Makefile->GetDefinition("CMAKE_OSX_DEPLOYMENT_TARGET");
std::string deploymentTargetFlagVar =
"CMAKE_" + lang + "_OSX_DEPLOYMENT_TARGET_FLAG";
- cmProp deploymentTargetFlag =
+ cmValue deploymentTargetFlag =
this->Makefile->GetDefinition(deploymentTargetFlagVar);
if (cmNonempty(deploymentTargetFlag) && cmNonempty(deploymentTarget)) {
flags += " ";
@@ -1943,11 +1960,11 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
std::string compilerSimulateId = this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_SIMULATE_ID"));
if (lang == "Swift") {
- if (cmProp v = target->GetProperty("Swift_LANGUAGE_VERSION")) {
- if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
- cmToCStr(this->Makefile->GetDefinition(
- "CMAKE_Swift_COMPILER_VERSION")),
- "4.2")) {
+ if (cmValue v = target->GetProperty("Swift_LANGUAGE_VERSION")) {
+ if (cmSystemTools::VersionCompare(
+ cmSystemTools::OP_GREATER_EQUAL,
+ this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"),
+ "4.2")) {
this->AppendFlags(flags, "-swift-version " + *v);
}
}
@@ -1974,7 +1991,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
// Add VFS Overlay for Clang compilers
if (compiler == "Clang") {
- if (cmProp vfsOverlay =
+ if (cmValue vfsOverlay =
this->Makefile->GetDefinition("CMAKE_CLANG_VFS_OVERLAY")) {
if (compilerSimulateId == "MSVC") {
this->AppendCompileOptions(
@@ -1989,10 +2006,10 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
// Add MSVC runtime library flags. This is activated by the presence
// of a default selection whether or not it is overridden by a property.
- cmProp msvcRuntimeLibraryDefault =
+ cmValue msvcRuntimeLibraryDefault =
this->Makefile->GetDefinition("CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT");
if (cmNonempty(msvcRuntimeLibraryDefault)) {
- cmProp msvcRuntimeLibraryValue =
+ cmValue msvcRuntimeLibraryValue =
target->GetProperty("MSVC_RUNTIME_LIBRARY");
if (!msvcRuntimeLibraryValue) {
msvcRuntimeLibraryValue = msvcRuntimeLibraryDefault;
@@ -2000,7 +2017,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
std::string const msvcRuntimeLibrary = cmGeneratorExpression::Evaluate(
*msvcRuntimeLibraryValue, this, config, target);
if (!msvcRuntimeLibrary.empty()) {
- if (cmProp msvcRuntimeLibraryOptions = this->Makefile->GetDefinition(
+ if (cmValue msvcRuntimeLibraryOptions = this->Makefile->GetDefinition(
"CMAKE_" + lang + "_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_" +
msvcRuntimeLibrary)) {
this->AppendCompileOptions(flags, *msvcRuntimeLibraryOptions);
@@ -2180,7 +2197,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
std::string const& optionFlagDef =
standardResolver.GetCompileOptionDef(target, lang, config);
if (!optionFlagDef.empty()) {
- cmProp opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef);
+ cmValue opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef);
if (opt) {
std::vector<std::string> optVec = cmExpandedList(*opt);
for (std::string const& i : optVec) {
@@ -2197,13 +2214,13 @@ static void AddVisibilityCompileOption(std::string& flags,
std::string* warnCMP0063)
{
std::string compileOption = "CMAKE_" + lang + "_COMPILE_OPTIONS_VISIBILITY";
- cmProp opt = lg->GetMakefile()->GetDefinition(compileOption);
+ cmValue opt = lg->GetMakefile()->GetDefinition(compileOption);
if (!opt) {
return;
}
std::string flagDefine = lang + "_VISIBILITY_PRESET";
- cmProp prop = target->GetProperty(flagDefine);
+ cmValue prop = target->GetProperty(flagDefine);
if (!prop) {
return;
}
@@ -2233,7 +2250,7 @@ static void AddInlineVisibilityCompileOption(std::string& flags,
{
std::string compileOption =
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN");
- cmProp opt = lg->GetMakefile()->GetDefinition(compileOption);
+ cmValue opt = lg->GetMakefile()->GetDefinition(compileOption);
if (!opt) {
return;
}
@@ -2430,7 +2447,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
return;
}
- cmProp ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX");
+ cmValue ispcHeaderSuffixProp = target->GetProperty("ISPC_HEADER_SUFFIX");
assert(ispcHeaderSuffixProp);
std::vector<std::string> ispcArchSuffixes =
@@ -2443,7 +2460,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
std::string rootObjectDir = target->GetObjectDirectory(config);
std::string headerDir = rootObjectDir;
- if (cmProp prop = target->GetProperty("ISPC_HEADER_DIRECTORY")) {
+ if (cmValue prop = target->GetProperty("ISPC_HEADER_DIRECTORY")) {
headerDir = cmSystemTools::CollapseFullPath(
cmStrCat(this->GetBinaryDirectory(), '/', *prop));
}
@@ -2493,6 +2510,16 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
static const std::array<std::string, 4> langs = { { "C", "CXX", "OBJC",
"OBJCXX" } };
+ bool haveAnyPch = false;
+ if (this->GetGlobalGenerator()->IsXcode()) {
+ for (const std::string& lang : langs) {
+ const std::string pchHeader = target->GetPchHeader(config, lang, "");
+ if (!pchHeader.empty()) {
+ haveAnyPch = true;
+ }
+ }
+ }
+
for (const std::string& lang : langs) {
auto langSources = std::count_if(
sources.begin(), sources.end(), [lang](cmSourceFile* sf) {
@@ -2533,17 +2560,22 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
const std::string pchHeader = target->GetPchHeader(config, lang, arch);
if (pchSource.empty() || pchHeader.empty()) {
+ if (this->GetGlobalGenerator()->IsXcode() && haveAnyPch) {
+ for (auto* sf : sources) {
+ sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
+ }
+ }
continue;
}
- const std::string pchExtension =
- this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION");
+ cmValue pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
- if (pchExtension.empty()) {
+ if (pchExtension.IsEmpty()) {
continue;
}
- cmProp ReuseFrom =
+ cmValue ReuseFrom =
target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
auto* pch_sf = this->Makefile->GetOrCreateSource(
@@ -2590,8 +2622,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
// MSVC 2008 is producing both .pdb and .idb files with /Zi.
bool msvc2008OrLess =
- cmSystemTools::VersionCompare(
- cmSystemTools::OP_LESS, compilerVersion.c_str(), "16.0") &&
+ cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ compilerVersion, "16.0") &&
compilerId == "MSVC";
// but not when used via toolset -Tv90
if (this->Makefile->GetSafeDefinition(
@@ -2622,7 +2654,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
cmStrCat(" ",
this->ConvertToOutputFormat(pchSourceObj, SHELL)),
true);
- } else {
+ } else if (reuseTarget->GetType() ==
+ cmStateEnums::OBJECT_LIBRARY) {
target->Target->AppendProperty(
"INTERFACE_LINK_LIBRARIES",
cmStrCat("$<$<CONFIG:", config,
@@ -2630,7 +2663,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
}
}
} else {
- pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str());
+ pch_sf->SetProperty("PCH_EXTENSION", pchExtension);
}
// Add pchHeader to source files, which will
@@ -2665,8 +2698,8 @@ void cmLocalGenerator::CopyPchCompilePdb(
cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
target->GetName(), ".dir/");
- const std::string copy_script =
- cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake");
+ const std::string copy_script = cmStrCat(
+ target_compile_pdb_dir, "copy_idb_pdb_", config.c_str(), ".cmake");
cmGeneratedFileStream file(copy_script);
file << "# CMake generated file\n";
@@ -2721,7 +2754,7 @@ void cmLocalGenerator::CopyPchCompilePdb(
bool stdPipesUTF8 = true;
auto configGenex = [&](cm::string_view expr) -> std::string {
- if (this->GetGlobalGenerator()->IsVisualStudio()) {
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
return cmStrCat("$<$<CONFIG:", config, ">:", expr, ">");
}
return std::string(expr);
@@ -2740,8 +2773,8 @@ void cmLocalGenerator::CopyPchCompilePdb(
std::vector<std::string> no_byproducts;
std::vector<std::string> outputs;
- outputs.push_back(
- cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb"));
+ outputs.push_back(configGenex(
+ cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb")));
if (this->GetGlobalGenerator()->IsVisualStudio()) {
this->AddCustomCommandToTarget(
@@ -2771,13 +2804,13 @@ inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf,
std::string const& filename)
{
target->AddSourceFileToUnityBatch(sf->ResolveFullPath());
- sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str());
+ sf->SetProperty("UNITY_SOURCE_FILE", filename);
}
}
void cmLocalGenerator::IncludeFileInUnitySources(
cmGeneratedFileStream& unity_file, std::string const& sf_full_path,
- cmProp beforeInclude, cmProp afterInclude, cmProp uniqueIdName) const
+ cmValue beforeInclude, cmValue afterInclude, cmValue uniqueIdName) const
{
if (cmNonempty(uniqueIdName)) {
std::string pathToHash;
@@ -2815,14 +2848,14 @@ void cmLocalGenerator::IncludeFileInUnitySources(
std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
- cmProp afterInclude, std::string const& filename_base, size_t batchSize)
+ std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
+ cmValue afterInclude, std::string const& filename_base, size_t batchSize)
{
if (batchSize == 0) {
batchSize = filtered_sources.size();
}
- cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
+ cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
std::vector<std::string> unity_files;
for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0;
@@ -2858,8 +2891,8 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeAuto(
std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
- cmProp afterInclude, std::string const& filename_base)
+ std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
+ cmValue afterInclude, std::string const& filename_base)
{
std::vector<std::string> unity_files;
@@ -2867,7 +2900,7 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
// without a group
std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping;
for (cmSourceFile* sf : filtered_sources) {
- if (cmProp value = sf->GetProperty("UNITY_GROUP")) {
+ if (cmValue value = sf->GetProperty("UNITY_GROUP")) {
auto i = explicit_mapping.find(*value);
if (i == explicit_mapping.end()) {
std::vector<cmSourceFile*> sources{ sf };
@@ -2878,7 +2911,7 @@ std::vector<std::string> cmLocalGenerator::AddUnityFilesModeGroup(
}
}
- cmProp uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
+ cmValue uniqueIdName = target->GetProperty("UNITY_BUILD_UNIQUE_ID");
for (auto const& item : explicit_mapping) {
auto const& name = item.first;
@@ -2925,15 +2958,15 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
std::vector<cmSourceFile*> sources;
target->GetSourceFiles(sources, config);
- cmProp batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE");
+ cmValue batchSizeString = target->GetProperty("UNITY_BUILD_BATCH_SIZE");
const size_t unityBatchSize = batchSizeString
? static_cast<size_t>(std::atoi(batchSizeString->c_str()))
: 0;
- cmProp beforeInclude =
+ cmValue beforeInclude =
target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE");
- cmProp afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE");
- cmProp unityMode = target->GetProperty("UNITY_BUILD_MODE");
+ cmValue afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE");
+ cmValue unityMode = target->GetProperty("UNITY_BUILD_MODE");
for (std::string lang : { "C", "CXX" }) {
std::vector<cmSourceFile*> filtered_sources;
@@ -2969,7 +3002,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
auto* unity = this->GetMakefile()->GetOrCreateSource(file);
target->AddSource(file, true);
unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON");
- unity->SetProperty("UNITY_SOURCE_FILE", file.c_str());
+ unity->SetProperty("UNITY_SOURCE_FILE", file);
}
}
}
@@ -2993,7 +3026,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
}
const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
- cmProp rawFlagsList = this->Makefile->GetDefinition(name);
+ cmValue rawFlagsList = this->Makefile->GetDefinition(name);
if (!rawFlagsList) {
return;
}
@@ -3039,6 +3072,30 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
}
}
+bool cmLocalGenerator::AppendLWYUFlags(std::string& flags,
+ const cmGeneratorTarget* target,
+ const std::string& lang)
+{
+ auto useLWYU = target->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
+ (target->GetType() == cmStateEnums::TargetType::EXECUTABLE ||
+ target->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY);
+
+ if (useLWYU) {
+ const auto& lwyuFlag = this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", lang, "_LINK_WHAT_YOU_USE_FLAG"));
+ useLWYU = !lwyuFlag.empty();
+
+ if (useLWYU) {
+ std::vector<BT<std::string>> lwyuOpts;
+ lwyuOpts.emplace_back(lwyuFlag);
+ this->AppendFlags(flags, target->ResolveLinkerWrapper(lwyuOpts, lang));
+ }
+ }
+
+ return useLWYU;
+}
+
void cmLocalGenerator::AppendCompileOptions(std::string& options,
std::string const& options_list,
const char* regex) const
@@ -3184,7 +3241,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines,
// Lookup the define flag for the current language.
std::string dflag = "-D";
if (!lang.empty()) {
- cmProp df =
+ cmValue df =
this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG"));
if (cmNonempty(df)) {
dflag = *df;
@@ -3231,7 +3288,7 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags,
const std::string& lang,
const char* feature)
{
- cmProp optionList = this->Makefile->GetDefinition(
+ cmValue optionList = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature));
if (optionList) {
std::vector<std::string> options = cmExpandedList(*optionList);
@@ -3241,8 +3298,8 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags,
}
}
-cmProp cmLocalGenerator::GetFeature(const std::string& feature,
- const std::string& config)
+cmValue cmLocalGenerator::GetFeature(const std::string& feature,
+ const std::string& config)
{
std::string featureName = feature;
// TODO: Define accumulation policy for features (prepend, append,
@@ -3253,7 +3310,7 @@ cmProp cmLocalGenerator::GetFeature(const std::string& feature,
}
cmStateSnapshot snp = this->StateSnapshot;
while (snp.IsValid()) {
- if (cmProp value = snp.GetDirectory().GetProperty(featureName)) {
+ if (cmValue value = snp.GetDirectory().GetProperty(featureName)) {
return value;
}
snp = snp.GetBuildsystemDirectoryParent();
@@ -3318,7 +3375,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
}
// Include the user-specified pre-install script for this target.
- if (cmProp preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
+ if (cmValue preinstall = l->GetProperty("PRE_INSTALL_SCRIPT")) {
cmInstallScriptGenerator g(*preinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
@@ -3371,7 +3428,7 @@ void cmLocalGenerator::GenerateTargetInstallRules(
}
// Include the user-specified post-install script for this target.
- if (cmProp postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
+ if (cmValue postinstall = l->GetProperty("POST_INSTALL_SCRIPT")) {
cmInstallScriptGenerator g(*postinstall, false, "", false, false);
g.Generate(os, config, configurationTypes);
}
@@ -3596,8 +3653,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
// Ensure that for the CMakeFiles/<target>.dir/generated_source_file
// we don't end up having:
// CMakeFiles/<target>.dir/CMakeFiles/<target>.dir/generated_source_file.obj
- cmProp unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE");
- cmProp pchExtension = source.GetProperty("PCH_EXTENSION");
+ cmValue unitySourceFile = source.GetProperty("UNITY_SOURCE_FILE");
+ cmValue pchExtension = source.GetProperty("PCH_EXTENSION");
const bool isPchObject = objectName.find("cmake_pch") != std::string::npos;
if (unitySourceFile || pchExtension || isPchObject) {
if (pchExtension) {
@@ -3696,7 +3753,7 @@ KWIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility()
unsigned int major = 0;
unsigned int minor = 0;
unsigned int patch = 0;
- if (cmProp value =
+ if (cmValue value =
this->Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY")) {
switch (sscanf(value->c_str(), "%u.%u.%u", &major, &minor, &patch)) {
case 2:
@@ -3723,8 +3780,9 @@ bool cmLocalGenerator::NeedBackwardsCompatibility_2_4()
// variable.
switch (this->GetPolicyStatus(cmPolicies::CMP0001)) {
case cmPolicies::WARN:
- // WARN is just OLD without warning because user code does not
- // always affect whether this check is done.
+ // WARN is just OLD without warning because user code does not
+ // always affect whether this check is done.
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// Old behavior is to check the variable.
break;
@@ -3791,7 +3849,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
static void cmLGInfoProp(cmMakefile* mf, cmGeneratorTarget* target,
const std::string& prop)
{
- if (cmProp val = target->GetProperty(prop)) {
+ if (cmValue val = target->GetProperty(prop)) {
mf->AddDefinition(prop, *val);
}
}
@@ -3801,7 +3859,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
const std::string& fname)
{
// Find the Info.plist template.
- cmProp in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
+ cmValue in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
std::string inFile = cmNonempty(in) ? *in : "MacOSXBundleInfo.plist.in";
if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile);
@@ -3840,7 +3898,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
const std::string& fname)
{
// Find the Info.plist template.
- cmProp in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
+ cmValue in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
std::string inFile = cmNonempty(in) ? *in : "MacOSXFrameworkInfo.plist.in";
if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile);
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 993280ac2..3614c8466 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -20,8 +20,8 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmStateSnapshot.h"
+#include "cmValue.h"
class cmCompiledGeneratorExpression;
class cmComputeLinkInformation;
@@ -171,6 +171,8 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+ bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target,
+ const std::string& lang);
enum class IncludePathStyle
{
@@ -245,7 +247,7 @@ public:
void AppendFeatureOptions(std::string& flags, const std::string& lang,
const char* feature);
- cmProp GetFeature(const std::string& feature, const std::string& config);
+ cmValue GetFeature(const std::string& feature, const std::string& config);
/** \brief Get absolute path to dependency \a name
*
@@ -545,7 +547,7 @@ public:
void CreateEvaluationFileOutputs(const std::string& config);
void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
- cmProp GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
+ cmValue GetRuleLauncher(cmGeneratorTarget* target, const std::string& prop);
protected:
// The default implementation ignores the IncludePathStyle and always
@@ -587,7 +589,7 @@ protected:
std::string::size_type ObjectPathMax;
std::set<std::string> ObjectMaxPathViolations;
- std::set<std::string> EnvCPATH;
+ std::vector<std::string> EnvCPATH;
using GeneratorTargetMap =
std::unordered_map<std::string, cmGeneratorTarget*>;
@@ -649,7 +651,7 @@ private:
void ComputeObjectMaxPath();
bool AllAppleArchSysrootsAreTheSame(const std::vector<std::string>& archs,
- const char* sysroot);
+ cmValue sysroot);
void CopyPchCompilePdb(const std::string& config, cmGeneratorTarget* target,
const std::string& ReuseFrom,
@@ -657,16 +659,16 @@ private:
std::vector<std::string> const& extensions);
void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file,
std::string const& sf_full_path,
- cmProp beforeInclude, cmProp afterInclude,
- cmProp uniqueIdName) const;
+ cmValue beforeInclude, cmValue afterInclude,
+ cmValue uniqueIdName) const;
std::vector<std::string> AddUnityFilesModeAuto(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
- cmProp afterInclude, std::string const& filename_base, size_t batchSize);
+ std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
+ cmValue afterInclude, std::string const& filename_base, size_t batchSize);
std::vector<std::string> AddUnityFilesModeGroup(
cmGeneratorTarget* target, std::string const& lang,
- std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude,
- cmProp afterInclude, std::string const& filename_base);
+ std::vector<cmSourceFile*> const& filtered_sources, cmValue beforeInclude,
+ cmValue afterInclude, std::string const& filename_base);
};
#if !defined(CMAKE_BOOTSTRAP)
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index e88f33c2f..8556fe6b5 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -27,7 +27,6 @@
#include "cmMessageType.h"
#include "cmNinjaTargetGenerator.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
@@ -35,6 +34,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
@@ -279,7 +279,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion();
// Ninja generator uses the 'console' pool if available (>= 1.5)
- if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) {
+ if (this->GetGlobalNinjaGenerator()->SupportsDirectConsole()) {
requiredVersion =
cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool();
}
@@ -311,7 +311,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
- cmProp jobpools =
+ cmValue jobpools =
this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS");
if (!jobpools) {
jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS");
@@ -796,8 +796,9 @@ cmLocalNinjaGenerator::MakeCustomCommandGenerators(
bool transformDepfile = false;
switch (cc.GetCMP0116Status()) {
- case cmPolicies::OLD:
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
@@ -869,7 +870,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements(
std::string cmLocalNinjaGenerator::MakeCustomLauncher(
cmCustomCommandGenerator const& ccg)
{
- cmProp property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");
+ cmValue property_value = this->Makefile->GetProperty("RULE_LAUNCH_CUSTOM");
if (!cmNonempty(property_value)) {
return std::string();
@@ -903,7 +904,7 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
void cmLocalNinjaGenerator::AdditionalCleanFiles(const std::string& config)
{
- if (cmProp prop_value =
+ if (cmValue prop_value =
this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
std::vector<std::string> cleanFiles;
{
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 0667c55a3..7e39b91f1 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -33,7 +33,6 @@
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
@@ -43,6 +42,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTargetDepend.h"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -570,7 +570,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
// Mark the rule as symbolic if requested.
if (symbolic) {
- if (cmProp sym =
+ if (cmValue sym =
this->Makefile->GetDefinition("CMAKE_MAKE_SYMBOLIC_RULE")) {
os << tgt << space << ": " << *sym << "\n";
}
@@ -884,7 +884,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend(
{
// Add a dependency on the rule file itself unless an option to skip
// it is specifically enabled by the user or project.
- cmProp nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
+ cmValue nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY");
if (cmIsOff(nodep)) {
depends.emplace_back(ruleFileName);
}
@@ -999,7 +999,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
std::string launcher;
// Short-circuit if there is no launcher.
- cmProp val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
+ cmValue val = this->GetRuleLauncher(target, "RULE_LAUNCH_CUSTOM");
if (cmNonempty(val)) {
// Expand rule variables referenced in the given launcher command.
cmRulePlaceholderExpander::RuleVariables vars;
@@ -1125,7 +1125,7 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
{
std::vector<std::string> cleanFiles;
// Look for additional files registered for cleaning in this directory.
- if (cmProp prop_value =
+ if (cmValue prop_value =
this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) {
cmExpandList(cmGeneratorExpression::Evaluate(
*prop_value, this,
@@ -1501,18 +1501,18 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
// Lookup useful directory information.
if (haveDirectoryInfo) {
// Test whether we need to force Unix paths.
- if (cmProp force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) {
+ if (cmValue force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) {
if (!cmIsOff(force)) {
cmSystemTools::SetForceUnixPaths(true);
}
}
// Setup relative path top directories.
- if (cmProp relativePathTopSource =
+ if (cmValue relativePathTopSource =
mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) {
this->SetRelativePathTopSource(*relativePathTopSource);
}
- if (cmProp relativePathTopBinary =
+ if (cmValue relativePathTopBinary =
mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) {
this->SetRelativePathTopBinary(*relativePathTopBinary);
}
@@ -1582,7 +1582,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
cmMakefile* mf = this->Makefile;
// Get the string listing the multiple output pairs.
- cmProp pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
+ cmValue pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
if (!pairs_string) {
return;
}
@@ -1654,7 +1654,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
std::vector<std::string> commands;
std::vector<std::string> depends;
- cmProp p = gt->GetProperty("EchoString");
+ cmValue p = gt->GetProperty("EchoString");
const char* text = p ? p->c_str() : "Running external command ...";
depends.reserve(gt->GetUtilities().size());
for (BT<std::pair<std::string, bool>> const& u : gt->GetUtilities()) {
@@ -1754,7 +1754,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall");
commands.clear();
depends.clear();
- cmProp noall =
+ cmValue noall =
this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
if (cmIsOff(noall)) {
// Drive the build before installing.
@@ -1804,7 +1804,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
bool verbose)
{
// Get the list of target files to check
- cmProp infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
+ cmValue infoDef = mf->GetDefinition("CMAKE_DEPEND_INFO_FILES");
if (!infoDef) {
return;
}
@@ -1903,7 +1903,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
// Tell the dependency scanner what compiler is used.
std::string cidVar = cmStrCat("CMAKE_", lang, "_COMPILER_ID");
- cmProp cid = this->Makefile->GetDefinition(cidVar);
+ cmValue cid = this->Makefile->GetDefinition(cidVar);
if (cmNonempty(cid)) {
cmakefileStream << "set(CMAKE_" << lang << "_COMPILER_ID \"" << *cid
<< "\")\n";
@@ -1960,11 +1960,11 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
// Store include transform rule properties. Write the directory
// rules first because they may be overridden by later target rules.
std::vector<std::string> transformRules;
- if (cmProp xform =
+ if (cmValue xform =
this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
cmExpandList(*xform, transformRules);
}
- if (cmProp xform =
+ if (cmValue xform =
target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
cmExpandList(*xform, transformRules);
}
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 14dd0baf4..78aa7f9c2 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -299,7 +299,7 @@ private:
cmGeneratorTarget const* target)
{
return this->CommandsVisited[target];
- };
+ }
std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>>
CommandsVisited;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 151470b4e..5d3e11a64 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -69,7 +69,7 @@ void cmLocalVisualStudio7Generator::AddHelperCommands()
if (!l->IsInBuildSystem()) {
continue;
}
- cmProp path = l->GetProperty("EXTERNAL_MSPROJECT");
+ cmValue path = l->GetProperty("EXTERNAL_MSPROJECT");
if (path) {
this->ReadAndStoreExternalGUID(l->GetName(), path->c_str());
}
@@ -402,6 +402,7 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = {
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue },
{ "PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "",
cmVS7FlagTable::UserValueRequired },
+ { "UsePrecompiledHeader", "Y-", "Don't use precompiled header", "0", 0 },
{ "PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "",
cmVS7FlagTable::UserValue },
// The YX and Yu options are in a per-global-generator table because
@@ -566,7 +567,7 @@ public:
} else {
this->Stream << this->LG->EscapeForXML("\n");
}
- std::string script = this->LG->ConstructScript(ccg);
+ std::string script = this->LG->ConstructScript(ccg, unmanaged);
this->Stream << this->LG->EscapeForXML(script);
}
@@ -582,7 +583,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
const std::string& libName, cmGeneratorTarget* target)
{
std::string mfcFlag;
- if (cmProp p = this->Makefile->GetDefinition("CMAKE_MFC_FLAG")) {
+ if (cmValue p = this->Makefile->GetDefinition("CMAKE_MFC_FLAG")) {
mfcFlag = cmGeneratorExpression::Evaluate(*p, this, configName);
} else {
mfcFlag = "0";
@@ -781,7 +782,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"" << tool << "\"\n";
if (this->FortranProject) {
- cmProp target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY");
+ cmValue target_mod_dir = target->GetProperty("Fortran_MODULE_DIRECTORY");
std::string modDir;
if (target_mod_dir) {
modDir = this->MaybeRelativeToCurBinDir(*target_mod_dir);
@@ -938,7 +939,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
" " + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
}
- cmProp targetLinkFlags = target->GetProperty("LINK_FLAGS");
+ cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
extraLinkOptions += " ";
extraLinkOptions += *targetLinkFlags;
@@ -1077,7 +1078,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
}
}
std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
- cmProp stackVal = this->Makefile->GetDefinition(stackVar);
+ cmValue stackVal = this->Makefile->GetDefinition(stackVar);
if (stackVal) {
fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\"\n";
}
@@ -1168,7 +1169,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
<< "\"\n";
}
std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
- cmProp stackVal = this->Makefile->GetDefinition(stackVar);
+ cmValue stackVal = this->Makefile->GetDefinition(stackVar);
if (stackVal) {
fout << "\t\t\t\tStackReserveSize=\"" << *stackVal << "\"";
}
@@ -1209,8 +1210,8 @@ void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool(
std::ostream& fout, std::string const& config, cmGeneratorTarget* target)
{
if (this->WindowsCEProject) {
- cmProp dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
- cmProp additionalFiles =
+ cmValue dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
+ cmValue additionalFiles =
target->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
if (!dir && !additionalFiles) {
@@ -1447,12 +1448,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
needfc = true;
}
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = sf.GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = sf.GetProperty(COMPILE_FLAGS)) {
fc.CompileFlags = genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
needfc = true;
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = sf.GetProperty(COMPILE_OPTIONS)) {
+ if (cmValue coptions = sf.GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
fc.CompileFlags,
genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
@@ -1504,25 +1505,25 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
}
}
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- if (cmProp cdefs = sf.GetProperty(COMPILE_DEFINITIONS)) {
+ if (cmValue cdefs = sf.GetProperty(COMPILE_DEFINITIONS)) {
fc.CompileDefs = genexInterpreter.Evaluate(*cdefs, COMPILE_DEFINITIONS);
needfc = true;
}
std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
- if (cmProp ccdefs = sf.GetProperty(defPropName)) {
+ if (cmValue ccdefs = sf.GetProperty(defPropName)) {
fc.CompileDefsConfig =
genexInterpreter.Evaluate(*ccdefs, COMPILE_DEFINITIONS);
needfc = true;
}
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
+ if (cmValue cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
fc.IncludeDirs = genexInterpreter.Evaluate(*cincs, INCLUDE_DIRECTORIES);
needfc = true;
}
// Check for extra object-file dependencies.
- if (cmProp deps = sf.GetProperty("OBJECT_DEPENDS")) {
+ if (cmValue deps = sf.GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> depends = cmExpandedList(*deps);
const char* sep = "";
for (const std::string& d : depends) {
@@ -1779,7 +1780,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule(
}
std::string comment = this->ConstructComment(ccg);
- std::string script = this->ConstructScript(ccg);
+ std::string script = this->ConstructScript(ccg, unmanaged);
if (this->FortranProject) {
cmSystemTools::ReplaceString(script, "$(Configuration)", config);
}
@@ -1897,9 +1898,9 @@ void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout,
{
// if we have all the required Source code control tags
// then add that to the project
- cmProp vsProjectname = target->GetProperty("VS_SCC_PROJECTNAME");
- cmProp vsLocalpath = target->GetProperty("VS_SCC_LOCALPATH");
- cmProp vsProvider = target->GetProperty("VS_SCC_PROVIDER");
+ cmValue vsProjectname = target->GetProperty("VS_SCC_PROJECTNAME");
+ cmValue vsLocalpath = target->GetProperty("VS_SCC_LOCALPATH");
+ cmValue vsProvider = target->GetProperty("VS_SCC_PROVIDER");
if (vsProvider && vsLocalpath && vsProjectname) {
/* clang-format off */
@@ -1908,7 +1909,7 @@ void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout,
<< "\tSccProvider=\"" << *vsProvider << "\"\n";
/* clang-format on */
- cmProp vsAuxPath = target->GetProperty("VS_SCC_AUXPATH");
+ cmValue vsAuxPath = target->GetProperty("VS_SCC_AUXPATH");
if (vsAuxPath) {
fout << "\tSccAuxPath=\"" << *vsAuxPath << "\"\n";
}
@@ -1928,7 +1929,7 @@ void cmLocalVisualStudio7Generator::WriteProjectStartFortran(
<< "\tProjectCreator=\"Intel Fortran\"\n"
<< "\tVersion=\"" << gg->GetIntelProjectVersion() << "\"\n";
/* clang-format on */
- cmProp p = target->GetProperty("VS_KEYWORD");
+ cmValue p = target->GetProperty("VS_KEYWORD");
const char* keyword = p ? p->c_str() : "Console Application";
const char* projectType = 0;
switch (target->GetType()) {
@@ -1990,14 +1991,14 @@ void cmLocalVisualStudio7Generator::WriteProjectStart(
<< "\tProjectType=\"Visual C++\"\n";
/* clang-format on */
fout << "\tVersion=\"" << (gg->GetVersion() / 10) << ".00\"\n";
- cmProp p = target->GetProperty("PROJECT_LABEL");
+ cmValue p = target->GetProperty("PROJECT_LABEL");
const std::string projLabel = p ? *p : libName;
p = target->GetProperty("VS_KEYWORD");
const std::string keyword = p ? *p : "Win32Proj";
fout << "\tName=\"" << projLabel << "\"\n";
fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n";
this->WriteProjectSCC(fout, target);
- if (cmProp targetFrameworkVersion =
+ if (cmValue targetFrameworkVersion =
target->GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
fout << "\tTargetFrameworkVersion=\"" << *targetFrameworkVersion << "\"\n";
}
@@ -2142,7 +2143,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
// save the GUID in the cache
this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
- guidStoreName, parser.GUID.c_str(), "Stored GUID", cmStateEnums::INTERNAL);
+ guidStoreName, parser.GUID, "Stored GUID", cmStateEnums::INTERNAL);
}
std::string cmLocalVisualStudio7Generator::GetTargetDirectory(
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 002f484bc..4ed1dd92b 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -124,7 +124,8 @@ const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const
}
std::string cmLocalVisualStudioGenerator::ConstructScript(
- cmCustomCommandGenerator const& ccg, const std::string& newline_text)
+ cmCustomCommandGenerator const& ccg, IsManaged isManaged,
+ const std::string& newline_text)
{
bool useLocal = this->CustomCommandUseLocal();
std::string workingDirectory = ccg.GetWorkingDirectory();
@@ -171,8 +172,9 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
// for visual studio IDE add extra stuff to the PATH
// if CMAKE_MSVCIDE_RUN_PATH is set.
- if (this->Makefile->GetDefinition("MSVC_IDE")) {
- cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
+ if (this->GetGlobalGenerator()->IsVisualStudio()) {
+ cmValue extraPath =
+ this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
if (extraPath) {
script += newline;
newline = newline_text;
@@ -236,6 +238,14 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
script += newline;
script += "if %errorlevel% neq 0 goto ";
script += this->GetReportErrorLabel();
+ if (isManaged == managed) {
+ // These aren't generated by default for C# projects.
+ script += newline;
+ script += this->GetReportErrorLabel();
+ script += newline;
+ script += "exit /b 0";
+ script += newline;
+ }
}
return script;
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 91fb6b061..0e7f63ff5 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -31,7 +31,13 @@ public:
virtual ~cmLocalVisualStudioGenerator();
/** Construct a script from the given list of command lines. */
+ enum IsManaged
+ {
+ unmanaged,
+ managed
+ };
std::string ConstructScript(cmCustomCommandGenerator const& ccg,
+ IsManaged isManaged,
const std::string& newline = "\n");
/** Label to which to jump in a batch file after a failed step in a
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index c970abe8a..83984f7a3 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -190,7 +190,7 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
{
// Warn if a <pkg>_ROOT variable we may use is set.
std::string const varName = pkg + "_ROOT";
- cmProp var = this->GetDefinition(varName);
+ cmValue var = this->GetDefinition(varName);
std::string env;
cmSystemTools::GetEnv(varName, env);
@@ -212,59 +212,31 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
}
}
-cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
+cmBTStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
}
-cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const
-{
- return this->StateSnapshot.GetDirectory()
- .GetIncludeDirectoriesEntryBacktraces();
-}
-
-cmStringRange cmMakefile::GetCompileOptionsEntries() const
+cmBTStringRange cmMakefile::GetCompileOptionsEntries() const
{
return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries();
}
-cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const
-{
- return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces();
-}
-
-cmStringRange cmMakefile::GetCompileDefinitionsEntries() const
+cmBTStringRange cmMakefile::GetCompileDefinitionsEntries() const
{
return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries();
}
-cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const
-{
- return this->StateSnapshot.GetDirectory()
- .GetCompileDefinitionsEntryBacktraces();
-}
-
-cmStringRange cmMakefile::GetLinkOptionsEntries() const
+cmBTStringRange cmMakefile::GetLinkOptionsEntries() const
{
return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries();
}
-cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const
-{
- return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces();
-}
-
-cmStringRange cmMakefile::GetLinkDirectoriesEntries() const
+cmBTStringRange cmMakefile::GetLinkDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries();
}
-cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const
-{
- return this->StateSnapshot.GetDirectory()
- .GetLinkDirectoriesEntryBacktraces();
-}
-
cmListFileBacktrace cmMakefile::GetBacktrace() const
{
return this->Backtrace;
@@ -428,7 +400,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
// Check for maximum recursion depth.
int depth = CMake_DEFAULT_RECURSION_LIMIT;
- cmProp depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
+ cmValue depthStr = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
if (depthStr) {
std::istringstream s(*depthStr);
int d;
@@ -614,7 +586,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011()
bool cmMakefile::ReadDependentFile(const std::string& filename,
bool noPolicyScope)
{
- if (cmProp def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) {
+ if (cmValue def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) {
this->AddDefinition("CMAKE_PARENT_LIST_FILE", *def);
}
std::string filenametoread = cmSystemTools::CollapseFullPath(
@@ -846,6 +818,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const
// version.
this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
msg.str(), this->Backtrace);
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to use policy version 2.4 set in
// cmListFileCache.
@@ -857,7 +830,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const
this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
msg.str(), this->Backtrace);
cmSystemTools::SetFatalErrorOccured();
- return;
+ break;
}
}
}
@@ -952,10 +925,9 @@ void cmMakefile::DoGenerate(cmLocalGenerator& lg)
void cmMakefile::Generate(cmLocalGenerator& lg)
{
this->DoGenerate(lg);
- cmProp oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
+ cmValue oldValue = this->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
if (oldValue &&
- cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue->c_str(),
- "2.4")) {
+ cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, oldValue, "2.4")) {
this->GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR,
"You have set CMAKE_BACKWARDS_COMPATIBILITY to a CMake version less "
@@ -1030,6 +1002,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\n";
issueMessage = true;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::NEW:
@@ -1037,6 +1010,7 @@ cmTarget* cmMakefile::GetCustomCommandTarget(
case cmPolicies::REQUIRED_ALWAYS:
issueMessage = true;
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (issueMessage) {
@@ -1386,10 +1360,10 @@ void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
{
if (before) {
this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(
- directory, this->Backtrace);
+ BT<std::string>(directory, this->Backtrace));
} else {
this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(
- directory, this->Backtrace);
+ BT<std::string>(directory, this->Backtrace));
}
}
@@ -1434,7 +1408,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
const char* define = def.c_str() + 2;
if (remove) {
- if (cmProp cdefs = this->GetProperty("COMPILE_DEFINITIONS")) {
+ if (cmValue cdefs = this->GetProperty("COMPILE_DEFINITIONS")) {
// Expand the list.
std::vector<std::string> defs = cmExpandedList(*cdefs);
@@ -1444,7 +1418,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
std::string ndefs = cmJoin(cmMakeRange(defBegin, defEnd), ";");
// Store the new list.
- this->SetProperty("COMPILE_DEFINITIONS", ndefs.c_str());
+ this->SetProperty("COMPILE_DEFINITIONS", ndefs);
}
} else {
// Append the definition to the directory property.
@@ -1465,30 +1439,29 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
// Include transform property. There is no per-config version.
{
const char* prop = "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM";
- this->SetProperty(prop, cmToCStr(parent->GetProperty(prop)));
+ this->SetProperty(prop, parent->GetProperty(prop));
}
// compile definitions property and per-config versions
cmPolicies::PolicyStatus polSt = this->GetPolicyStatus(cmPolicies::CMP0043);
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
this->SetProperty("COMPILE_DEFINITIONS",
- cmToCStr(parent->GetProperty("COMPILE_DEFINITIONS")));
+ parent->GetProperty("COMPILE_DEFINITIONS"));
std::vector<std::string> configs =
this->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
for (std::string const& config : configs) {
std::string defPropName =
cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
- cmProp prop = parent->GetProperty(defPropName);
- this->SetProperty(defPropName, cmToCStr(prop));
+ cmValue prop = parent->GetProperty(defPropName);
+ this->SetProperty(defPropName, prop);
}
}
// labels
- this->SetProperty("LABELS", cmToCStr(parent->GetProperty("LABELS")));
+ this->SetProperty("LABELS", parent->GetProperty("LABELS"));
// link libraries
- this->SetProperty("LINK_LIBRARIES",
- cmToCStr(parent->GetProperty("LINK_LIBRARIES")));
+ this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES"));
// the initial project name
this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName());
@@ -1781,6 +1754,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
<< cmPolicies::GetPolicyWarning(cmPolicies::CMP0014);
/* clang-format on */
this->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior does not warn.
break;
@@ -1791,6 +1765,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
case cmPolicies::NEW:
// NEW behavior prints the error.
this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ break;
}
return;
}
@@ -1877,16 +1852,16 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs,
std::string entryString = cmJoin(incs, ";");
if (before) {
this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry(
- entryString, this->Backtrace);
+ BT<std::string>(entryString, this->Backtrace));
} else {
this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry(
- entryString, this->Backtrace);
+ BT<std::string>(entryString, this->Backtrace));
}
// Property on each target:
for (auto& target : this->Targets) {
cmTarget& t = target.second;
- t.InsertInclude(entryString, this->Backtrace, before);
+ t.InsertInclude(BT<std::string>(entryString, this->Backtrace), before);
}
}
@@ -1927,7 +1902,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
cmStateEnums::CacheEntryType type,
bool force)
{
- cmProp existingValue = this->GetState()->GetInitializedCacheValue(name);
+ cmValue existingValue = this->GetState()->GetInitializedCacheValue(name);
// must be outside the following if() to keep it alive long enough
std::string nvalue;
@@ -1956,7 +1931,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value,
nvalue += files[cc];
}
- this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type);
+ this->GetCMakeInstance()->AddCacheEntry(name, nvalue, doc, type);
nvalue = *this->GetState()->GetInitializedCacheValue(name);
value = nvalue.c_str();
}
@@ -2045,7 +2020,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target)
default:;
}
- if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
+ if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp);
for (auto j = linkLibs.begin(); j != linkLibs.end(); ++j) {
@@ -2118,15 +2093,23 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type,
const std::string& name)
{
- auto it = this->Targets
- .emplace(name,
- cmTarget(name, type, cmTarget::VisibilityNormal, this,
- cmTarget::PerConfig::Yes))
- .first;
+ return &this->CreateNewTarget(name, type).first;
+}
+
+std::pair<cmTarget&, bool> cmMakefile::CreateNewTarget(
+ const std::string& name, cmStateEnums::TargetType type,
+ cmTarget::PerConfig perConfig)
+{
+ auto ib = this->Targets.emplace(
+ name, cmTarget(name, type, cmTarget::VisibilityNormal, this, perConfig));
+ auto it = ib.first;
+ if (!ib.second) {
+ return std::make_pair(std::ref(it->second), false);
+ }
this->OrderedTargets.push_back(&it->second);
this->GetGlobalGenerator()->IndexTarget(&it->second);
this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name);
- return &it->second;
+ return std::make_pair(std::ref(it->second), true);
}
cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
@@ -2235,7 +2218,7 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(
cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name)
{
std::string delimiters;
- if (cmProp p = this->GetDefinition("SOURCE_GROUP_DELIMITER")) {
+ if (cmValue p = this->GetDefinition("SOURCE_GROUP_DELIMITER")) {
delimiters = *p;
} else {
delimiters = "/\\";
@@ -2288,7 +2271,7 @@ void cmMakefile::ExpandVariablesCMP0019()
}
std::ostringstream w;
- cmProp includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
+ cmValue includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
if (includeDirs && mightExpandVariablesCMP0019(includeDirs->c_str())) {
std::string dirs = *includeDirs;
this->ExpandVariablesInString(dirs, true, true);
@@ -2300,7 +2283,7 @@ void cmMakefile::ExpandVariablesCMP0019()
<< " " << dirs << "\n";
/* clang-format on */
}
- this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
+ this->SetProperty("INCLUDE_DIRECTORIES", dirs);
}
// Also for each target's INCLUDE_DIRECTORIES property:
@@ -2326,7 +2309,7 @@ void cmMakefile::ExpandVariablesCMP0019()
}
}
- if (cmProp linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
+ if (cmValue linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
if (mightExpandVariablesCMP0019(linkDirsProp->c_str())) {
std::string d = *linkDirsProp;
const std::string orig = d;
@@ -2342,7 +2325,7 @@ void cmMakefile::ExpandVariablesCMP0019()
}
}
- if (cmProp linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
+ if (cmValue linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
std::vector<std::string> linkLibs = cmExpandedList(*linkLibsProp);
for (auto l = linkLibs.begin(); l != linkLibs.end(); ++l) {
@@ -2386,7 +2369,7 @@ bool cmMakefile::IsOn(const std::string& name) const
bool cmMakefile::IsSet(const std::string& name) const
{
- cmProp value = this->GetDefinition(name);
+ cmValue value = this->GetDefinition(name);
if (!value) {
return false;
}
@@ -2404,12 +2387,12 @@ bool cmMakefile::IsSet(const std::string& name) const
bool cmMakefile::PlatformIs32Bit() const
{
- if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+ if (cmValue plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
if (*plat_abi == "ELF X32") {
return false;
}
}
- if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
+ if (cmValue sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
return atoi(sizeof_dptr->c_str()) == 4;
}
return false;
@@ -2417,7 +2400,7 @@ bool cmMakefile::PlatformIs32Bit() const
bool cmMakefile::PlatformIs64Bit() const
{
- if (cmProp sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
+ if (cmValue sizeof_dptr = this->GetDefinition("CMAKE_SIZEOF_VOID_P")) {
return atoi(sizeof_dptr->c_str()) == 8;
}
return false;
@@ -2425,7 +2408,7 @@ bool cmMakefile::PlatformIs64Bit() const
bool cmMakefile::PlatformIsx32() const
{
- if (cmProp plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
+ if (cmValue plat_abi = this->GetDefinition("CMAKE_INTERNAL_PLATFORM_ABI")) {
if (*plat_abi == "ELF X32") {
return true;
}
@@ -2475,7 +2458,7 @@ const char* cmMakefile::GetSONameFlag(const std::string& language) const
name += language;
}
name += "_FLAG";
- return cmToCStr(this->GetDefinition(name));
+ return this->GetDefinition(name).GetCStr();
}
bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const
@@ -2498,7 +2481,7 @@ const std::string& cmMakefile::GetRequiredDefinition(
const std::string& name) const
{
static std::string const empty;
- cmProp def = this->GetDefinition(name);
+ cmValue def = this->GetDefinition(name);
if (!def) {
cmSystemTools::Error("Error required internal CMake variable not "
"set, cmake may not be built correctly.\n"
@@ -2511,7 +2494,7 @@ const std::string& cmMakefile::GetRequiredDefinition(
bool cmMakefile::IsDefinitionSet(const std::string& name) const
{
- cmProp def = this->StateSnapshot.GetDefinition(name);
+ cmValue def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
@@ -2528,7 +2511,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const
bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const
{
- cmProp def = this->StateSnapshot.GetDefinition(name);
+ cmValue def = this->StateSnapshot.GetDefinition(name);
#ifndef CMAKE_BOOTSTRAP
if (cmVariableWatch* vv = this->GetVariableWatch()) {
if (!def) {
@@ -2540,9 +2523,9 @@ bool cmMakefile::IsNormalDefinitionSet(const std::string& name) const
return def != nullptr;
}
-cmProp cmMakefile::GetDefinition(const std::string& name) const
+cmValue cmMakefile::GetDefinition(const std::string& name) const
{
- cmProp def = this->StateSnapshot.GetDefinition(name);
+ cmValue def = this->StateSnapshot.GetDefinition(name);
if (!def) {
def = this->GetState()->GetInitializedCacheValue(name);
}
@@ -2553,7 +2536,7 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const
vv->VariableAccessed(name,
def ? cmVariableWatch::VARIABLE_READ_ACCESS
: cmVariableWatch::UNKNOWN_VARIABLE_READ_ACCESS,
- cmToCStr(def), this);
+ def.GetCStr(), this);
if (watch_function_executed) {
// A callback was executed and may have caused re-allocation of the
@@ -2571,19 +2554,14 @@ cmProp cmMakefile::GetDefinition(const std::string& name) const
const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const
{
- static std::string const empty;
- cmProp def = this->GetDefinition(name);
- if (!def) {
- return empty;
- }
- return *def;
+ return this->GetDefinition(name);
}
bool cmMakefile::GetDefExpandList(const std::string& name,
std::vector<std::string>& out,
bool emptyArgs) const
{
- cmProp def = this->GetDefinition(name);
+ cmValue def = this->GetDefinition(name);
if (!def) {
return false;
}
@@ -2736,7 +2714,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld(
// Lookup the definition of VAR.
std::string var(first + 1, last - first - 2);
- if (cmProp val = this->GetDefinition(var)) {
+ if (cmValue val = this->GetDefinition(var)) {
// Store the value in the output escaping as requested.
if (escapeQuotes) {
source.append(cmEscapeQuotes(*val));
@@ -2808,6 +2786,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld(
case cmPolicies::REQUIRED_ALWAYS:
error << "\n"
<< cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0010);
+ break;
case cmPolicies::NEW:
// NEW behavior is to report the error.
break;
@@ -2941,7 +2920,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
openstack.pop_back();
result.append(last, in - last);
std::string const& lookup = result.substr(var.loc);
- cmProp value = nullptr;
+ cmValue value = nullptr;
std::string varresult;
std::string svalue;
switch (var.domain) {
@@ -2959,7 +2938,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
break;
case ENVIRONMENT:
if (cmSystemTools::GetEnv(lookup, svalue)) {
- value = &svalue;
+ value = cmValue(svalue);
}
break;
case CACHE:
@@ -3086,7 +3065,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
if (filename && variable == lineVar) {
varresult = std::to_string(line);
} else {
- cmProp def = this->GetDefinition(variable);
+ cmValue def = this->GetDefinition(variable);
if (def) {
varresult = *def;
} else if (!this->SuppressSideEffects) {
@@ -3105,8 +3084,8 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
break;
}
}
- // Failed to find a valid @ expansion; treat it as literal.
- /* FALLTHROUGH */
+ // Failed to find a valid @ expansion; treat it as literal.
+ CM_FALLTHROUGH;
default: {
if (!openstack.empty() &&
!(isalnum(inc) || inc == '_' || inc == '/' || inc == '.' ||
@@ -3182,6 +3161,23 @@ void cmMakefile::RemoveVariablesInString(std::string& source,
}
}
+void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault)
+{
+ if (this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
+ return;
+ }
+ std::string initConfigs;
+ if (!cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) {
+ initConfigs = genDefault;
+ }
+ this->AddCacheDefinition(
+ "CMAKE_CONFIGURATION_TYPES", initConfigs,
+ "Semicolon separated list of supported configuration types, "
+ "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
+ "anything else will be ignored.",
+ cmStateEnums::STRING);
+}
+
std::string cmMakefile::GetDefaultConfiguration() const
{
if (this->GetGlobalGenerator()->IsMultiConfig()) {
@@ -3542,8 +3538,8 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// make sure the same generator is used
// use this program as the cmake to be run, it should not
// be run that way but the cmake object requires a vailid path
- cmake cm(cmake::RoleProject, cmState::Project);
- cm.SetIsInTryCompile(true);
+ cmake cm(cmake::RoleProject, cmState::Project,
+ cmState::ProjectKind::TryCompile);
auto gg = cm.CreateGlobalGenerator(this->GetGlobalGenerator()->GetName());
if (!gg) {
this->IssueMessage(MessageType::INTERNAL_ERROR,
@@ -3565,18 +3561,19 @@ int cmMakefile::TryCompile(const std::string& srcdir,
cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"));
cm.LoadCache();
if (!cm.GetGlobalGenerator()->IsMultiConfig()) {
- if (cmProp config =
+ if (cmValue config =
this->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION")) {
// Tell the single-configuration generator which one to use.
// Add this before the user-provided CMake arguments in case
// one of the arguments is -DCMAKE_BUILD_TYPE=...
- cm.AddCacheEntry("CMAKE_BUILD_TYPE", config->c_str(),
- "Build configuration", cmStateEnums::STRING);
+ cm.AddCacheEntry("CMAKE_BUILD_TYPE", config, "Build configuration",
+ cmStateEnums::STRING);
}
}
- cmProp recursionDepth = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
+ cmValue recursionDepth =
+ this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH");
if (recursionDepth) {
- cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth->c_str(),
+ cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth,
"Maximum recursion depth", cmStateEnums::STRING);
}
// if cmake args were provided then pass them in
@@ -3709,7 +3706,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename,
std::string moduleInCMakeModulePath;
// Always search in CMAKE_MODULE_PATH:
- cmProp cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH");
+ cmValue cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH");
if (cmakeModulePath) {
std::vector<std::string> modulePath = cmExpandedList(*cmakeModulePath);
@@ -3750,7 +3747,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename,
}
if (!moduleInCMakeModulePath.empty() && !moduleInCMakeRoot.empty()) {
- cmProp currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE");
+ cmValue currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE");
std::string mods = cmSystemTools::GetCMakeRoot() + "/Modules/";
if (currentFile && cmSystemTools::IsSubDirectory(*currentFile, mods)) {
switch (this->GetPolicyStatus(cmPolicies::CMP0017)) {
@@ -3807,7 +3804,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
// Replace #cmakedefine instances.
if (this->cmDefineRegex.find(line)) {
- cmProp def = this->GetDefinition(this->cmDefineRegex.match(2));
+ cmValue def = this->GetDefinition(this->cmDefineRegex.match(2));
if (!cmIsOff(def)) {
const std::string indentation = this->cmDefineRegex.match(1);
cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine",
@@ -3820,7 +3817,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output,
}
} else if (this->cmDefine01Regex.find(line)) {
const std::string indentation = this->cmDefine01Regex.match(1);
- cmProp def = this->GetDefinition(this->cmDefine01Regex.match(2));
+ cmValue def = this->GetDefinition(this->cmDefine01Regex.match(2));
cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine01",
"#" + indentation + "define");
output += line;
@@ -3966,6 +3963,10 @@ void cmMakefile::SetProperty(const std::string& prop, const char* value)
{
this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
}
+void cmMakefile::SetProperty(const std::string& prop, cmValue value)
+{
+ this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
+}
void cmMakefile::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
@@ -3974,26 +3975,25 @@ void cmMakefile::AppendProperty(const std::string& prop,
this->Backtrace);
}
-cmProp cmMakefile::GetProperty(const std::string& prop) const
+cmValue cmMakefile::GetProperty(const std::string& prop) const
{
// Check for computed properties.
static std::string output;
if (prop == "TESTS") {
std::vector<std::string> keys;
// get list of keys
- std::transform(this->Tests.begin(), this->Tests.end(),
- std::back_inserter(keys),
- [](decltype(this->Tests)::value_type const& pair) {
- return pair.first;
- });
+ const auto* t = this;
+ std::transform(
+ t->Tests.begin(), t->Tests.end(), std::back_inserter(keys),
+ [](decltype(t->Tests)::value_type const& pair) { return pair.first; });
output = cmJoin(keys, ";");
- return &output;
+ return cmValue(output);
}
return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
-cmProp cmMakefile::GetProperty(const std::string& prop, bool chain) const
+cmValue cmMakefile::GetProperty(const std::string& prop, bool chain) const
{
return this->StateSnapshot.GetDirectory().GetProperty(prop, chain);
}
@@ -4052,7 +4052,7 @@ void cmMakefile::GetTests(const std::string& config,
void cmMakefile::AddCMakeDependFilesFromUser()
{
std::vector<std::string> deps;
- if (cmProp deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) {
+ if (cmValue deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) {
cmExpandList(*deps_str, deps);
}
for (std::string const& dep : deps) {
@@ -4341,7 +4341,7 @@ static std::string const nMatchesVariable = "CMAKE_MATCH_COUNT";
void cmMakefile::ClearMatches()
{
- cmProp nMatchesStr = this->GetDefinition(nMatchesVariable);
+ cmValue nMatchesStr = this->GetDefinition(nMatchesVariable);
if (!nMatchesStr) {
return;
}
@@ -4394,7 +4394,7 @@ cmPolicies::PolicyStatus cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id,
bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) const
{
// Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting.
- if (cmProp val = this->GetDefinition(var)) {
+ if (cmValue val = this->GetDefinition(var)) {
return cmIsOn(val);
}
// Enable optional policy warnings with --debug-output, --trace,
@@ -4426,13 +4426,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
return false;
}
- // Deprecate old policies, especially those that require a lot
- // of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 &&
+ // Deprecate old policies.
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
- id == cmPolicies::CMP0065))) {
+ id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) {
this->IssueMessage(MessageType::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
@@ -4511,7 +4510,8 @@ bool cmMakefile::IgnoreErrorsCMP0061() const
bool ignoreErrors = true;
switch (this->GetPolicyStatus(cmPolicies::CMP0061)) {
case cmPolicies::WARN:
- // No warning for this policy!
+ // No warning for this policy!
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 77e9c7405..671cdab46 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -13,6 +13,7 @@
#include <stack>
#include <string>
#include <unordered_map>
+#include <utility>
#include <vector>
#include <cm/optional>
@@ -28,11 +29,10 @@
#include "cmMessageType.h"
#include "cmNewLineStyle.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmSourceFileLocationKind.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
+#include "cmValue.h"
// IWYU does not see that 'std::unordered_map<std::string, cmTarget>'
// will not compile without the complete type.
@@ -230,6 +230,10 @@ public:
cmTarget* AddImportedTarget(const std::string& name,
cmStateEnums::TargetType type, bool global);
+ std::pair<cmTarget&, bool> CreateNewTarget(
+ const std::string& name, cmStateEnums::TargetType type,
+ cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes);
+
cmTarget* AddNewTarget(cmStateEnums::TargetType type,
const std::string& name);
@@ -282,6 +286,10 @@ public:
* can be used in CMake to refer to lists, directories, etc.
*/
void AddDefinition(const std::string& name, cm::string_view value);
+ void AddDefinition(const std::string& name, cmValue value)
+ {
+ this->AddDefinition(name, *value);
+ }
/**
* Add bool variable definition to the build.
*/
@@ -310,6 +318,8 @@ public:
*/
void SetProjectName(std::string const& name);
+ void InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault);
+
/* Get the default configuration */
std::string GetDefaultConfiguration() const;
@@ -392,13 +402,13 @@ public:
* Set a regular expression that include files must match
* in order to be considered as part of the depend information.
*/
- void SetIncludeRegularExpression(const char* regex)
+ void SetIncludeRegularExpression(const std::string& regex)
{
- this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex);
+ this->SetProperty("INCLUDE_REGULAR_EXPRESSION", regex.c_str());
}
- const char* GetIncludeRegularExpression() const
+ const std::string& GetIncludeRegularExpression() const
{
- return cmToCStr(this->GetProperty("INCLUDE_REGULAR_EXPRESSION"));
+ return this->GetProperty("INCLUDE_REGULAR_EXPRESSION");
}
/**
@@ -482,7 +492,7 @@ public:
* If the variable is not found in this makefile instance, the
* cache is then queried.
*/
- cmProp GetDefinition(const std::string&) const;
+ cmValue GetDefinition(const std::string&) const;
const std::string& GetSafeDefinition(const std::string&) const;
const std::string& GetRequiredDefinition(const std::string& name) const;
bool IsDefinitionSet(const std::string&) const;
@@ -762,10 +772,15 @@ public:
//! Set/Get a property of this directory
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmValue(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
- cmProp GetProperty(const std::string& prop) const;
- cmProp GetProperty(const std::string& prop, bool chain) const;
+ cmValue GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop, bool chain) const;
bool GetPropertyAsBool(const std::string& prop) const;
std::vector<std::string> GetPropertyKeys() const;
@@ -867,16 +882,11 @@ public:
bool CheckCMP0037(std::string const& targetName,
cmStateEnums::TargetType targetType) const;
- cmStringRange GetIncludeDirectoriesEntries() const;
- cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
- cmStringRange GetCompileOptionsEntries() const;
- cmBacktraceRange GetCompileOptionsBacktraces() const;
- cmStringRange GetCompileDefinitionsEntries() const;
- cmBacktraceRange GetCompileDefinitionsBacktraces() const;
- cmStringRange GetLinkOptionsEntries() const;
- cmBacktraceRange GetLinkOptionsBacktraces() const;
- cmStringRange GetLinkDirectoriesEntries() const;
- cmBacktraceRange GetLinkDirectoriesBacktraces() const;
+ cmBTStringRange GetIncludeDirectoriesEntries() const;
+ cmBTStringRange GetCompileOptionsEntries() const;
+ cmBTStringRange GetCompileDefinitionsEntries() const;
+ cmBTStringRange GetLinkOptionsEntries() const;
+ cmBTStringRange GetLinkDirectoriesEntries() const;
std::set<std::string> const& GetSystemIncludeDirectories() const
{
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index e7e4a2b6f..575fb0569 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -21,7 +21,6 @@
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -29,6 +28,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator(
cmGeneratorTarget* target)
@@ -195,6 +195,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
buildObjs, depends, useWatcomQuote);
+ std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
+
cmRulePlaceholderExpander::RuleVariables vars;
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
@@ -215,6 +217,7 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
cmOutputConverter::SHELL);
vars.Language = linkLanguage.c_str();
+ vars.AIXExports = aixExports.c_str();
vars.Objects = buildObjs.c_str();
vars.ObjectDir = objectDir.c_str();
vars.Target = target.c_str();
@@ -225,8 +228,8 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
std::string launcher;
- cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
- "RULE_LAUNCH_LINK");
+ cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
}
@@ -394,9 +397,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->GetLinkLibsCMP0065(
linkLanguage, *this->GeneratorTarget));
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed");
- }
+ this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(
+ linkFlags, this->GeneratorTarget, linkLanguage);
// Add language feature flags.
this->LocalGenerator->AddLanguageFlagsForLinking(
@@ -525,14 +527,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string manifests = this->GetManifests(this->GetConfigName());
- std::string const& aixExports = this->GetAIXExports(this->GetConfigName());
-
cmRulePlaceholderExpander::RuleVariables vars;
vars.CMTargetName = this->GeneratorTarget->GetName().c_str();
vars.CMTargetType =
cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
vars.Language = linkLanguage.c_str();
- vars.AIXExports = aixExports.c_str();
vars.Objects = buildObjs.c_str();
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
@@ -577,18 +576,24 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.Launcher = linkerLauncher.c_str();
}
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand =
- cmStrCat(this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=", targetOutPathReal);
- real_link_commands.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmValue lwyuCheck =
+ this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck);
+ cmakeCommand += cmStrCat(" --source=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
+ }
}
std::string launcher;
- cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
- "RULE_LAUNCH_LINK");
+ cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
}
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d0e3837dd..ace73a77e 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -21,7 +21,6 @@
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -29,6 +28,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator(
cmGeneratorTarget* target)
@@ -178,9 +178,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags,
this->GetConfigName());
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
- }
+ this->UseLWYU = this->LocalGenerator->AppendLWYUFlags(
+ extraFlags, this->GeneratorTarget, linkLanguage);
+
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
@@ -362,8 +362,8 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
std::string launcher;
- cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
- "RULE_LAUNCH_LINK");
+ cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
}
@@ -811,8 +811,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
std::string launcher;
- cmProp val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
- "RULE_LAUNCH_LINK");
+ cmValue val = this->LocalGenerator->GetRuleLauncher(this->GeneratorTarget,
+ "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
}
@@ -871,13 +871,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Get the set of commands.
std::string linkRule = this->GetLinkRule(linkRuleVar);
cmExpandList(linkRule, real_link_commands);
- if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
- (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) {
- std::string cmakeCommand = cmStrCat(
- this->LocalGenerator->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=", targetOutPathReal);
- real_link_commands.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmValue lwyuCheck =
+ this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->LocalGenerator->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck);
+ cmakeCommand += cmStrCat(" --source=", targetOutPathReal);
+ real_link_commands.push_back(std::move(cmakeCommand));
+ }
}
// Expand placeholders.
diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx
index 86188db4c..337f78bf7 100644
--- a/Source/cmMakefileProfilingData.cxx
+++ b/Source/cmMakefileProfilingData.cxx
@@ -29,7 +29,7 @@ cmMakefileProfilingData::cmMakefileProfilingData(
}
this->ProfileStream << "[";
-};
+}
cmMakefileProfilingData::~cmMakefileProfilingData() noexcept
{
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 945827701..8edadd31e 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -16,8 +16,6 @@
#include <cmext/algorithm>
#include <cmext/string_view>
-#include "cm_codecvt.hxx"
-
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
@@ -36,7 +34,6 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
@@ -47,6 +44,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
@@ -59,11 +57,13 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
this->LocalGenerator->GetGlobalGenerator());
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
this->NoRuleMessages = false;
- if (cmProp ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) {
+ if (cmValue ruleStatus =
+ cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) {
this->NoRuleMessages = cmIsOff(*ruleStatus);
}
switch (this->GeneratorTarget->GetPolicyStatusCMP0113()) {
case cmPolicies::WARN:
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
this->CMP0113New = false;
break;
@@ -202,14 +202,14 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
};
// Look for additional files registered for cleaning in this directory.
- if (cmProp prop_value =
+ if (cmValue prop_value =
this->Makefile->GetProperty("ADDITIONAL_MAKE_CLEAN_FILES")) {
std::vector<std::string> const files = evaluatedFiles(*prop_value);
this->CleanFiles.insert(files.begin(), files.end());
}
// Look for additional files registered for cleaning in this target.
- if (cmProp prop_value =
+ if (cmValue prop_value =
this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
std::vector<std::string> const files = evaluatedFiles(*prop_value);
// For relative path support
@@ -289,14 +289,13 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
this->GeneratorTarget->GetExtraSources(extraSources, this->GetConfigName());
this->OSXBundleGenerator->GenerateMacOSXContentStatements(
extraSources, this->MacOSXContentGenerator.get(), this->GetConfigName());
- cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+ cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects,
this->GetConfigName());
for (cmSourceFile const* sf : externalObjects) {
auto const& objectFileName = sf->GetFullPath();
- if (!cmSystemTools::StringEndsWith(objectFileName,
- cmToCStr(pchExtension))) {
+ if (!cmHasSuffix(objectFileName, pchExtension)) {
this->ExternalObjects.push_back(objectFileName);
}
}
@@ -671,12 +670,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
cmSystemTools::GetFilenameWithoutLastExtension(objectName);
ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource);
- cmProp ispcSuffixProp =
+ cmValue ispcSuffixProp =
this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX");
assert(ispcSuffixProp);
std::string directory = this->GeneratorTarget->GetObjectDirectory(config);
- if (cmProp prop =
+ if (cmValue prop =
this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) {
directory =
cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop);
@@ -688,7 +687,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Add flags from source file properties.
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = source.GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = source.GetProperty(COMPILE_FLAGS)) {
const std::string& evaluatedFlags =
genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
@@ -698,7 +697,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = source.GetProperty(COMPILE_OPTIONS)) {
+ if (cmValue coptions = source.GetProperty(COMPILE_OPTIONS)) {
const std::string& evaluatedOptions =
genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS);
this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
@@ -732,7 +731,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::vector<std::string> includes;
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
+ if (cmValue cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
const std::string& evaluatedIncludes =
genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES);
this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes,
@@ -748,7 +747,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Add source-specific preprocessor definitions.
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- if (cmProp compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
+ if (cmValue compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
const std::string& evaluatedDefs =
genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS);
this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
@@ -757,7 +756,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
<< "\n";
}
std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
- if (cmProp config_compile_defs = source.GetProperty(defPropName)) {
+ if (cmValue config_compile_defs = source.GetProperty(defPropName)) {
const std::string& evaluatedDefs =
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS);
this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
@@ -947,11 +946,11 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
this->GetIncludes(lang, this->GetConfigName()));
}
- cmProp eliminate[] = {
+ cmValue eliminate[] = {
this->Makefile->GetDefinition("CMAKE_START_TEMP_FILE"),
this->Makefile->GetDefinition("CMAKE_END_TEMP_FILE")
};
- for (cmProp el : eliminate) {
+ for (cmValue el : eliminate) {
if (el) {
cmSystemTools::ReplaceString(compileCommand, *el, "");
}
@@ -968,7 +967,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
lang == "OBJCXX")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
if (cmNonempty(clauncher)) {
compilerLauncher = *clauncher;
}
@@ -978,10 +977,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
if (!compileCommands.empty() &&
(lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
std::string const tidy_prop = lang + "_CLANG_TIDY";
- cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop);
- cmProp iwyu = nullptr;
- cmProp cpplint = nullptr;
- cmProp cppcheck = nullptr;
+ cmValue tidy = this->GeneratorTarget->GetProperty(tidy_prop);
+ cmValue iwyu = nullptr;
+ cmValue cpplint = nullptr;
+ cmValue cppcheck = nullptr;
if (lang == "C" || lang == "CXX") {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
@@ -1002,12 +1001,30 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
}
if (cmNonempty(iwyu)) {
run_iwyu += " --iwyu=";
- run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
+
+ // Only add --driver-mode if it is not already specified, as adding
+ // it unconditionally might override a user-specified driver-mode
+ if (iwyu.Get()->find("--driver-mode=") == std::string::npos) {
+ cmValue p = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
+ std::string driverMode;
+
+ if (cmNonempty(p)) {
+ driverMode = *p;
+ } else {
+ driverMode = lang == "C" ? "gcc" : "g++";
+ }
+
+ run_iwyu += this->LocalGenerator->EscapeForShell(
+ cmStrCat(*iwyu, ";--driver-mode=", driverMode));
+ } else {
+ run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
+ }
}
if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
- cmProp p = this->Makefile->GetDefinition("CMAKE_" + lang +
- "_CLANG_TIDY_DRIVER_MODE");
+ cmValue p = this->Makefile->GetDefinition("CMAKE_" + lang +
+ "_CLANG_TIDY_DRIVER_MODE");
std::string driverMode;
if (cmNonempty(p)) {
driverMode = *p;
@@ -1051,7 +1068,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string launcher;
{
- cmProp val = this->LocalGenerator->GetRuleLauncher(
+ cmValue val = this->LocalGenerator->GetRuleLauncher(
this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
@@ -1121,7 +1138,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Check for extra outputs created by the compilation.
std::vector<std::string> outputs(1, relativeObj);
- if (cmProp extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) {
+ if (cmValue extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) {
std::string evaluated_outputs = cmGeneratorExpression::Evaluate(
*extra_outputs_str, this->LocalGenerator, config);
@@ -1176,7 +1193,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string preprocessRuleVar =
cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE");
- if (cmProp preprocessRule =
+ if (cmValue preprocessRule =
this->Makefile->GetDefinition(preprocessRuleVar)) {
std::vector<std::string> preprocessCommands =
cmExpandedList(*preprocessRule);
@@ -1221,7 +1238,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
std::string assemblyRuleVar =
cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE");
- if (cmProp assemblyRule =
+ if (cmValue assemblyRule =
this->Makefile->GetDefinition(assemblyRuleVar)) {
std::vector<std::string> assemblyCommands =
cmExpandedList(*assemblyRule);
@@ -1400,6 +1417,13 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
<< this->GeneratorTarget->GetFortranModuleDirectory(working_dir)
<< "\")\n";
+
+ if (this->GeneratorTarget->IsFortranBuildingInstrinsicModules()) {
+ *this->InfoFileStream
+ << "\n"
+ << "# Fortran compiler is building intrinsic modules.\n"
+ << "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES ON) \n";
+ }
/* clang-format on */
// and now write the rule to use it
@@ -1485,7 +1509,7 @@ void cmMakefileTargetGenerator::WriteObjectDependRules(
// Create the list of dependencies known at cmake time. These are
// shared between the object file and dependency scanning rule.
depends.push_back(source.GetFullPath());
- if (cmProp objectDeps = source.GetProperty("OBJECT_DEPENDS")) {
+ if (cmValue objectDeps = source.GetProperty("OBJECT_DEPENDS")) {
cmExpandList(*objectDeps, depends);
}
}
@@ -1724,10 +1748,10 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
std::string object;
const auto& lineContinue = this->GlobalGenerator->LineContinueDirective;
- cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+ cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
for (std::string const& obj : this->Objects) {
- if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) {
+ if (cmHasSuffix(obj, pchExtension)) {
continue;
}
*this->BuildFileStream << " " << lineContinue;
@@ -1811,13 +1835,13 @@ private:
void cmMakefileTargetGenerator::WriteObjectsStrings(
std::vector<std::string>& objStrings, std::string::size_type limit)
{
- cmProp pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
+ cmValue pchExtension = this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
cmMakefileTargetGeneratorObjectStrings helper(
objStrings, this->LocalGenerator,
this->LocalGenerator->GetStateSnapshot().GetDirectory(), limit);
for (std::string const& obj : this->Objects) {
- if (cmSystemTools::StringEndsWith(obj, cmToCStr(pchExtension))) {
+ if (cmHasSuffix(obj, pchExtension)) {
continue;
}
helper.Feed(obj);
@@ -1946,7 +1970,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule(
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_GNUtoMS_RULE");
- if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) {
+ if (cmValue rule = this->Makefile->GetDefinition(ruleVar)) {
linkRule += *rule;
}
}
@@ -1995,7 +2019,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
// Check for an explicit setting one way or the other.
std::string const responseVar =
"CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS";
- if (cmProp val = this->Makefile->GetDefinition(responseVar)) {
+ if (cmValue val = this->Makefile->GetDefinition(responseVar)) {
if (!val->empty()) {
return cmIsOn(val);
}
@@ -2034,7 +2058,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
// Check for an explicit setting one way or the other.
std::string const responseVar =
"CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES";
- if (cmProp val = this->Makefile->GetDefinition(responseVar)) {
+ if (cmValue val = this->Makefile->GetDefinition(responseVar)) {
if (!val->empty()) {
return cmIsOn(val);
}
@@ -2048,22 +2072,11 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
const char* name, std::string const& options,
std::vector<std::string>& makefile_depends)
{
- // FIXME: Find a better way to determine the response file encoding,
- // perhaps using tool-specific platform information variables.
- // For now, use the makefile encoding as a heuristic.
- codecvt::Encoding responseEncoding =
- this->GlobalGenerator->GetMakefileEncoding();
- // Non-MSVC tooling may not understand a BOM.
- if (responseEncoding == codecvt::UTF8_WITH_BOM &&
- !this->Makefile->IsOn("MSVC")) {
- responseEncoding = codecvt::UTF8;
- }
-
// Create the response file.
std::string responseFileNameFull =
cmStrCat(this->TargetBuildDirectoryFull, '/', name);
- cmGeneratedFileStream responseStream(responseFileNameFull, false,
- responseEncoding);
+ cmGeneratedFileStream responseStream(
+ responseFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding());
responseStream.SetCopyIfDifferent(true);
responseStream << options << "\n";
@@ -2109,7 +2122,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlag;
- if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) {
+ if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
responseFlag = *p;
} else {
responseFlag = "@";
@@ -2149,7 +2162,7 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlag;
- if (cmProp p = this->Makefile->GetDefinition(responseFlagVar)) {
+ if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
responseFlag = *p;
} else {
responseFlag = "@";
@@ -2244,7 +2257,7 @@ void cmMakefileTargetGenerator::GenDefFile(
cmd += this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeRelativeToCurBinDir(objlist_file),
cmOutputConverter::SHELL);
- cmProp nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
+ cmValue nm_executable = this->Makefile->GetDefinition("CMAKE_NM");
if (cmNonempty(nm_executable)) {
cmd += " --nm=";
cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index 45043faa5..73e5f33b5 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -10,6 +10,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
// cmMarkAsAdvancedCommand
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 5c21d1b7e..517d52955 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -32,7 +32,6 @@
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
@@ -41,6 +40,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
cmGeneratorTarget* target)
@@ -267,7 +267,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule(
vars.LanguageCompileFlags = "$LANGUAGE_COMPILE_FLAGS";
std::string launcher;
- cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmValue val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
@@ -390,7 +390,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
if (flag) {
responseFlag = *flag;
@@ -462,7 +462,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
}
std::string launcher;
- cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmValue val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
@@ -569,29 +569,35 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd(
// CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead.
std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable(
this->TargetLinkLanguage(config), config);
- cmProp linkCmd = mf->GetDefinition(linkCmdVar);
+ cmValue linkCmd = mf->GetDefinition(linkCmdVar);
if (linkCmd) {
std::string linkCmdStr = *linkCmd;
if (this->GetGeneratorTarget()->HasImplibGNUtoMS(config)) {
std::string ruleVar =
cmStrCat("CMAKE_", this->GeneratorTarget->GetLinkerLanguage(config),
"_GNUtoMS_RULE");
- if (cmProp rule = this->Makefile->GetDefinition(ruleVar)) {
+ if (cmValue rule = this->Makefile->GetDefinition(ruleVar)) {
linkCmdStr += *rule;
}
}
cmExpandList(linkCmdStr, linkCmds);
- if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
- std::string cmakeCommand = cmStrCat(
- this->GetLocalGenerator()->ConvertToOutputFormat(
- cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
- " -E __run_co_compile --lwyu=");
- cmGeneratorTarget& gt = *this->GetGeneratorTarget();
- std::string targetOutputReal = this->ConvertToNinjaPath(
- gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact,
- /*realname=*/true));
- cmakeCommand += targetOutputReal;
- linkCmds.push_back(std::move(cmakeCommand));
+ if (this->UseLWYU) {
+ cmValue lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK");
+ if (lwyuCheck) {
+ std::string cmakeCommand = cmStrCat(
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+ " -E __run_co_compile --lwyu=");
+ cmakeCommand +=
+ this->GetLocalGenerator()->EscapeForShell(*lwyuCheck);
+
+ std::string targetOutputReal =
+ this->ConvertToNinjaPath(this->GetGeneratorTarget()->GetFullPath(
+ config, cmStateEnums::RuntimeBinaryArtifact,
+ /*realname=*/true));
+ cmakeCommand += cmStrCat(" --source=", targetOutputReal);
+ linkCmds.push_back(std::move(cmakeCommand));
+ }
}
return linkCmds;
}
@@ -896,7 +902,7 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkStatement(
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
- this->EnsureParentDirectoryExists(impLibPath);
+ this->EnsureParentDirectoryExists(targetOutputImplib);
}
const std::string objPath =
@@ -1038,7 +1044,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
}();
vars["SWIFT_MODULE_NAME"] = [gt]() -> std::string {
- if (cmProp name = gt->GetProperty("Swift_MODULE_NAME")) {
+ if (cmValue name = gt->GetProperty("Swift_MODULE_NAME")) {
return *name;
}
return gt->GetName();
@@ -1047,13 +1053,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
vars["SWIFT_MODULE"] = [this](const std::string& module) -> std::string {
std::string directory =
this->GetLocalGenerator()->GetCurrentBinaryDirectory();
- if (cmProp prop = this->GetGeneratorTarget()->GetProperty(
+ if (cmValue prop = this->GetGeneratorTarget()->GetProperty(
"Swift_MODULE_DIRECTORY")) {
directory = *prop;
}
std::string name = module + ".swiftmodule";
- if (cmProp prop =
+ if (cmValue prop =
this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) {
name = *prop;
}
@@ -1156,12 +1162,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"],
config);
- if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
- (gt->GetType() == cmStateEnums::TargetType::EXECUTABLE ||
- gt->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY ||
- gt->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY)) {
- vars["LINK_FLAGS"] += " -Wl,--no-as-needed";
- }
+
+ this->UseLWYU = this->GetLocalGenerator()->AppendLWYUFlags(
+ vars["LINK_FLAGS"], this->GetGeneratorTarget(),
+ this->TargetLinkLanguage(config));
+
vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]);
vars["MANIFESTS"] = this->GetManifests(config);
@@ -1206,7 +1211,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
- this->EnsureParentDirectoryExists(impLibPath);
+ this->EnsureParentDirectoryExists(targetOutputImplib);
if (gt->HasImportLibrary(config)) {
// Some linkers may update a binary without touching its import lib.
byproducts.ExplicitOuts.emplace_back(targetOutputImplib);
@@ -1226,7 +1231,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
gt->GetFullNameComponents(prefix, base, suffix, config);
std::string dbg_suffix = ".dbg";
// TODO: Where to document?
- if (cmProp d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
+ if (cmValue d = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
dbg_suffix = *d;
}
vars["TARGET_PDB"] = base + suffix + dbg_suffix;
@@ -1292,7 +1297,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
obj_list_file, cmOutputConverter::SHELL);
- cmProp nm_executable = this->GetMakefile()->GetDefinition("CMAKE_NM");
+ cmValue nm_executable = this->GetMakefile()->GetDefinition("CMAKE_NM");
if (cmNonempty(nm_executable)) {
cmd += " --nm=";
cmd += this->LocalCommonGenerator->ConvertToOutputFormat(
@@ -1346,7 +1351,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
- cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
!(this->TargetLinkLanguage(config) == "RC" ||
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 609848b43..57657b1c7 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -31,7 +31,6 @@
#include "cmNinjaNormalTargetGenerator.h"
#include "cmNinjaUtilityTargetGenerator.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
@@ -40,6 +39,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
@@ -224,13 +224,13 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
- if (cmProp cflags = source->GetProperty(COMPILE_FLAGS)) {
+ if (cmValue cflags = source->GetProperty(COMPILE_FLAGS)) {
this->LocalGenerator->AppendFlags(
flags, genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
- if (cmProp coptions = source->GetProperty(COMPILE_OPTIONS)) {
+ if (cmValue coptions = source->GetProperty(COMPILE_OPTIONS)) {
this->LocalGenerator->AppendCompileOptions(
flags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
}
@@ -290,14 +290,14 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
}
const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
- if (cmProp compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
+ if (cmValue compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
this->LocalGenerator->AppendDefines(
defines, genexInterpreter.Evaluate(*compile_defs, COMPILE_DEFINITIONS));
}
std::string defPropName =
cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
- if (cmProp config_compile_defs = source->GetProperty(defPropName)) {
+ if (cmValue config_compile_defs = source->GetProperty(defPropName)) {
this->LocalGenerator->AppendDefines(
defines,
genexInterpreter.Evaluate(*config_compile_defs, COMPILE_DEFINITIONS));
@@ -318,7 +318,7 @@ std::string cmNinjaTargetGenerator::ComputeIncludes(
this->LocalGenerator, config, this->GeneratorTarget, language);
const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
- if (cmProp cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
+ if (cmValue cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
this->LocalGenerator->AppendIncludeDirectories(
includes, genexInterpreter.Evaluate(*cincludes, INCLUDE_DIRECTORIES),
*source);
@@ -638,7 +638,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmLocalGenerator::SHELL);
std::string launcher;
- cmProp val = this->GetLocalGenerator()->GetRuleLauncher(
+ cmValue val = this->GetLocalGenerator()->GetRuleLauncher(
this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
if (cmNonempty(val)) {
launcher = cmStrCat(*val, ' ');
@@ -771,11 +771,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
if (!mf->GetIsSourceFileTryCompile()) {
rule.DepType = "gcc";
rule.DepFile = "$DEP_FILE";
- cmProp d = mf->GetDefinition("CMAKE_C_COMPILER");
+ cmValue d = mf->GetDefinition("CMAKE_C_COMPILER");
const std::string cl =
d ? *d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
- cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang,
- ' ', vars.Source, " $DEP_FILE $out \"",
+ std::string cmcldepsPath;
+ cmSystemTools::GetShortPath(cmSystemTools::GetCMClDepsCommand(),
+ cmcldepsPath);
+ cldeps = cmStrCat(cmcldepsPath, ' ', lang, ' ', vars.Source,
+ " $DEP_FILE $out \"",
mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"),
"\" \"", cl, "\" ");
}
@@ -840,7 +843,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
lang == "HIP" || lang == "ISPC" || lang == "OBJC" ||
lang == "OBJCXX")) {
std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
- cmProp clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
if (cmNonempty(clauncher)) {
compilerLauncher = *clauncher;
}
@@ -850,10 +853,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
if (!compileCmds.empty() &&
(lang == "C" || lang == "CXX" || lang == "OBJC" || lang == "OBJCXX")) {
std::string const tidy_prop = cmStrCat(lang, "_CLANG_TIDY");
- cmProp tidy = this->GeneratorTarget->GetProperty(tidy_prop);
- cmProp iwyu = nullptr;
- cmProp cpplint = nullptr;
- cmProp cppcheck = nullptr;
+ cmValue tidy = this->GeneratorTarget->GetProperty(tidy_prop);
+ cmValue iwyu = nullptr;
+ cmValue cpplint = nullptr;
+ cmValue cppcheck = nullptr;
if (lang == "C" || lang == "CXX") {
std::string const iwyu_prop = cmStrCat(lang, "_INCLUDE_WHAT_YOU_USE");
iwyu = this->GeneratorTarget->GetProperty(iwyu_prop);
@@ -874,12 +877,30 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
compilerLauncher.clear();
}
if (cmNonempty(iwyu)) {
- run_iwyu += cmStrCat(" --iwyu=",
- this->GetLocalGenerator()->EscapeForShell(*iwyu));
+ run_iwyu += " --iwyu=";
+
+ // Only add --driver-mode if it is not already specified, as adding
+ // it unconditionally might override a user-specified driver-mode
+ if (iwyu.Get()->find("--driver-mode=") == std::string::npos) {
+ cmValue p = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE"));
+ std::string driverMode;
+
+ if (cmNonempty(p)) {
+ driverMode = *p;
+ } else {
+ driverMode = lang == "C" ? "gcc" : "g++";
+ }
+
+ run_iwyu += this->LocalGenerator->EscapeForShell(
+ cmStrCat(*iwyu, ";--driver-mode=", driverMode));
+ } else {
+ run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu);
+ }
}
if (cmNonempty(tidy)) {
run_iwyu += " --tidy=";
- cmProp p = this->Makefile->GetDefinition(
+ cmValue p = this->Makefile->GetDefinition(
cmStrCat("CMAKE_", lang, "_CLANG_TIDY_DRIVER_MODE"));
std::string driverMode;
if (cmNonempty(p)) {
@@ -986,7 +1007,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
config);
}
if (firstForConfig) {
- cmProp pchExtension =
+ cmValue pchExtension =
this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
std::vector<cmSourceFile const*> externalObjects;
@@ -994,8 +1015,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
for (cmSourceFile const* sf : externalObjects) {
auto objectFileName = this->GetGlobalGenerator()->ExpandCFGIntDir(
this->ConvertToNinjaPath(sf->GetFullPath()), config);
- if (!cmSystemTools::StringEndsWith(objectFileName,
- cmToCStr(pchExtension))) {
+ if (!cmHasSuffix(objectFileName, pchExtension)) {
this->Configs[config].Objects.push_back(objectFileName);
}
}
@@ -1092,7 +1112,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
"output-file-map.json");
std::string const targetSwiftDepsPath = [this, config]() -> std::string {
cmGeneratorTarget const* target = this->GeneratorTarget;
- if (cmProp name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
+ if (cmValue name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
return *name;
}
return this->ConvertToNinjaPath(
@@ -1216,7 +1236,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
// build response file name
std::string cmakeLinkVar = cmStrCat(cmakeVarLang, "_RESPONSE_FILE_FLAG");
- cmProp flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
+ cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
bool const lang_supports_response =
!(language == "RC" || (language == "CUDA" && !flag));
@@ -1258,10 +1278,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) {
- cmProp pchExtension =
+ cmValue pchExtension =
this->GetMakefile()->GetDefinition("CMAKE_PCH_EXTENSION");
- if (!cmSystemTools::StringEndsWith(objectFileName,
- cmToCStr(pchExtension))) {
+ if (!cmHasSuffix(objectFileName, pchExtension)) {
// Add this object to the list of object files.
this->Configs[config].Objects.push_back(objectFileName);
}
@@ -1299,7 +1318,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
- if (cmProp objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
+ if (cmValue objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> objDepList = cmExpandedList(*objectDeps);
std::copy(objDepList.begin(), objDepList.end(),
std::back_inserter(depList));
@@ -1445,13 +1464,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmSystemTools::GetFilenameWithoutLastExtension(objectName);
ispcSource = cmSystemTools::GetFilenameWithoutLastExtension(ispcSource);
- cmProp ispcSuffixProp =
+ cmValue ispcSuffixProp =
this->GeneratorTarget->GetProperty("ISPC_HEADER_SUFFIX");
assert(ispcSuffixProp);
std::string ispcHeaderDirectory =
this->GeneratorTarget->GetObjectDirectory(config);
- if (cmProp prop =
+ if (cmValue prop =
this->GeneratorTarget->GetProperty("ISPC_HEADER_DIRECTORY")) {
ispcHeaderDirectory =
cmStrCat(this->LocalGenerator->GetBinaryDirectory(), '/', *prop);
@@ -1502,7 +1521,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
objBuild, commandLineLengthLimit);
}
- if (cmProp objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
+ if (cmValue objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
std::string evaluatedObjectOutputs = cmGeneratorExpression::Evaluate(
*objectOutputs, this->LocalGenerator, config);
@@ -1582,13 +1601,13 @@ void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
std::string const objectFilePath =
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config));
std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
- if (cmProp name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
+ if (cmValue name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
return *name;
}
return cmStrCat(objectFilePath, ".swiftdeps");
}();
std::string const swiftDiaPath = [source, objectFilePath]() -> std::string {
- if (cmProp name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) {
+ if (cmValue name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) {
return *name;
}
return cmStrCat(objectFilePath, ".dia");
@@ -1696,7 +1715,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config)
{
- if (cmProp prop_value =
+ if (cmValue prop_value =
this->GeneratorTarget->GetProperty("ADDITIONAL_CLEAN_FILES")) {
cmLocalNinjaGenerator* lg = this->LocalGenerator;
std::vector<std::string> cleanFiles;
@@ -1730,7 +1749,7 @@ void cmNinjaTargetGenerator::EnsureDirectoryExists(
} else {
cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
std::string fullPath = gg->GetCMakeInstance()->GetHomeOutputDirectory();
- // Also ensures their is a trailing slash.
+ // Also ensures there is a trailing slash.
gg->StripNinjaOutputPathPrefixAsSuffix(fullPath);
fullPath += path;
cmSystemTools::MakeDirectory(fullPath);
@@ -1786,7 +1805,7 @@ void cmNinjaTargetGenerator::addPoolNinjaVariable(
const std::string& pool_property, cmGeneratorTarget* target,
cmNinjaVars& vars)
{
- cmProp pool = target->GetProperty(pool_property);
+ cmValue pool = target->GetProperty(pool_property);
if (pool) {
vars["pool"] = *pool;
}
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 1f5a7ff4c..15197ba27 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -18,12 +18,12 @@
#include "cmLocalNinjaGenerator.h"
#include "cmNinjaTypes.h"
#include "cmOutputConverter.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(
cmGeneratorTarget* target)
@@ -141,7 +141,7 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
std::string command = lg->BuildCommandLine(
commands, config, fileConfig, "utility", this->GeneratorTarget);
std::string desc;
- cmProp echoStr = genTarget->GetProperty("EchoString");
+ cmValue echoStr = genTarget->GetProperty("EchoString");
if (echoStr) {
desc = *echoStr;
} else {
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index bae67e04d..ec54fc590 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -6,11 +6,11 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
// cmOptionCommand
bool cmOptionCommand(std::vector<std::string> const& args,
@@ -29,12 +29,12 @@ bool cmOptionCommand(std::vector<std::string> const& args,
{
auto policyStatus =
status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077);
- const auto* existsBeforeSet =
+ const auto& existsBeforeSet =
status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
switch (policyStatus) {
case cmPolicies::WARN:
checkAndWarn = (existsBeforeSet != nullptr);
- break;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior does not warn.
break;
@@ -53,7 +53,7 @@ bool cmOptionCommand(std::vector<std::string> const& args,
// See if a cache variable with this name already exists
// If so just make sure the doc state is correct
cmState* state = status.GetMakefile().GetState();
- cmProp existingValue = state->GetCacheEntryValue(args[0]);
+ cmValue existingValue = state->GetCacheEntryValue(args[0]);
if (existingValue &&
(state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
@@ -77,7 +77,7 @@ bool cmOptionCommand(std::vector<std::string> const& args,
}
if (checkAndWarn) {
- const auto* existsAfterSet =
+ const auto& existsAfterSet =
status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
if (!existsAfterSet) {
status.GetMakefile().IssueMessage(
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 840fdb9ec..2b785e1d3 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -12,13 +12,14 @@
#include "cmStateDirectory.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
namespace {
bool PathEqOrSubDir(std::string const& a, std::string const& b)
{
return (cmSystemTools::ComparePath(a, b) ||
cmSystemTools::IsSubDirectory(a, b));
-};
+}
}
cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index d589614d7..ad276d2f7 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -15,11 +15,11 @@
#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
namespace {
/** \class cmDependInformation
@@ -118,7 +118,7 @@ public:
std::set<std::string> uniqueIncludes;
std::vector<std::string> orderedAndUniqueIncludes;
for (auto const& target : this->Makefile->GetTargets()) {
- cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
+ cmValue incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
if (!incDirProp) {
continue;
}
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 246506978..9f3fd00d3 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -13,10 +13,10 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
static std::string EscapeArg(const std::string& arg)
{
@@ -196,7 +196,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,
for (unsigned long i = argvStart; i < count; ++i) {
std::ostringstream argName;
argName << "ARGV" << i;
- cmProp arg = status.GetMakefile().GetDefinition(argName.str());
+ cmValue arg = status.GetMakefile().GetDefinition(argName.str());
if (!arg) {
status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR,
"PARSE_ARGV called with " +
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 01e8c047a..23000fae6 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -15,6 +15,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
static bool stringToId(const char* input, cmPolicies::PolicyID& pid)
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f7c0d2592..ce0411761 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -379,7 +379,13 @@ class cmMakefile;
3, 21, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0126, \
"set(CACHE) does not remove a normal variable of the same name.", 3, \
- 21, 0, cmPolicies::WARN)
+ 21, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0127, \
+ "cmake_dependent_option() supports full Condition Syntax.", 3, 22, \
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0128, \
+ "Selection of language standard and extension flags improved.", 3, \
+ 22, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 6950c19ef..20fcdbed9 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -15,10 +15,10 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
static bool IncludeByVariable(cmExecutionStatus& status,
const std::string& variable);
@@ -308,7 +308,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
}
std::string vw;
for (std::string const& i : vv) {
- cmProp v = mf.GetDefinition(i);
+ cmValue v = mf.GetDefinition(i);
if (cmNonempty(v)) {
if (cmp0048 == cmPolicies::WARN) {
if (!injectedProjectCommand) {
@@ -358,7 +358,7 @@ static bool IncludeByVariable(cmExecutionStatus& status,
const std::string& variable)
{
cmMakefile& mf = status.GetMakefile();
- cmProp include = mf.GetDefinition(variable);
+ cmValue include = mf.GetDefinition(variable);
if (!include) {
return true;
}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index 1e03c3f0f..07811092e 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -4,8 +4,6 @@
#include "cmConfigure.h" // IWYU pragma: keep
-#include <string>
-
class cmProperty
{
public:
@@ -22,15 +20,3 @@ public:
INSTALL
};
};
-
-using cmProp = const std::string*;
-
-inline const char* cmToCStr(cmProp p)
-{
- return p ? p->c_str() : nullptr;
-}
-
-inline const char* cmToCStrSafe(cmProp p)
-{
- return p ? p->c_str() : "";
-}
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 06e151ab6..b15000f49 100644
--- a/Source/cmPropertyMap.cxx
+++ b/Source/cmPropertyMap.cxx
@@ -19,6 +19,15 @@ void cmPropertyMap::SetProperty(const std::string& name, const char* value)
this->Map_[name] = value;
}
+void cmPropertyMap::SetProperty(const std::string& name, cmValue value)
+{
+ if (!value) {
+ this->Map_.erase(name);
+ return;
+ }
+
+ this->Map_[name] = *value;
+}
void cmPropertyMap::AppendProperty(const std::string& name,
const std::string& value, bool asString)
@@ -42,11 +51,11 @@ void cmPropertyMap::RemoveProperty(const std::string& name)
this->Map_.erase(name);
}
-cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const
+cmValue cmPropertyMap::GetPropertyValue(const std::string& name) const
{
auto it = this->Map_.find(name);
if (it != this->Map_.end()) {
- return &it->second;
+ return cmValue(it->second);
}
return nullptr;
}
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index cda585a89..f50b65e21 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -9,7 +9,7 @@
#include <utility>
#include <vector>
-#include "cmProperty.h"
+#include "cmValue.h"
/** \class cmPropertyMap
* \brief String property map.
@@ -26,13 +26,18 @@ public:
//! Set the property value
void SetProperty(const std::string& name, const char* value);
+ void SetProperty(const std::string& name, cmValue value);
+ void SetProperty(const std::string& name, const std::string& value)
+ {
+ this->SetProperty(name, cmValue(value));
+ }
//! Append to the property value
void AppendProperty(const std::string& name, const std::string& value,
bool asString = false);
//! Get the property value
- cmProp GetPropertyValue(const std::string& name) const;
+ cmValue GetPropertyValue(const std::string& name) const;
//! Remove the property @a name from the map
void RemoveProperty(const std::string& name);
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index e9670f9c3..ca0b259dc 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -6,7 +6,6 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStringAlgorithms.h"
@@ -41,7 +40,7 @@ bool cmQTWrapCPPCommand(std::vector<std::string> const& args,
cmStrCat(mf.GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
cmSourceFile* sf = mf.GetOrCreateSource(newName, true);
if (curr) {
- sf->SetProperty("ABSTRACT", cmToCStr(curr->GetProperty("ABSTRACT")));
+ sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT"));
}
// Compute the name of the header from which to generate the file.
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 57fcd2da7..9584e5c41 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -24,7 +24,8 @@
/// @arg valueOpts list of options that accept a value
void MergeOptions(std::vector<std::string>& baseOpts,
std::vector<std::string> const& newOpts,
- std::initializer_list<cm::string_view> valueOpts, bool isQt5)
+ std::initializer_list<cm::string_view> valueOpts,
+ bool isQt5OrLater)
{
if (newOpts.empty()) {
return;
@@ -47,7 +48,7 @@ void MergeOptions(std::vector<std::string>& baseOpts,
auto oit = newOpt.begin();
if (*oit == '-') {
++oit;
- if (isQt5 && (*oit == '-')) {
+ if (isQt5OrLater && (*oit == '-')) {
++oit;
}
optName.assign(oit, newOpt.end());
@@ -204,24 +205,24 @@ std::string cmQtAutoGen::AppendFilenameSuffix(cm::string_view filename,
void cmQtAutoGen::UicMergeOptions(std::vector<std::string>& baseOpts,
std::vector<std::string> const& newOpts,
- bool isQt5)
+ bool isQt5OrLater)
{
static std::initializer_list<cm::string_view> const valueOpts = {
"tr", "translate", "postfix", "generator",
"include", // Since Qt 5.3
"g"
};
- MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5OrLater);
}
void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
std::vector<std::string> const& newOpts,
- bool isQt5)
+ bool isQt5OrLater)
{
static std::initializer_list<cm::string_view> const valueOpts = {
"name", "root", "compress", "threshold"
};
- MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
+ MergeOptions(baseOpts, newOpts, valueOpts, isQt5OrLater);
}
static void RccListParseContent(std::string const& content,
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 466a954a9..5a23ae924 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -93,12 +93,12 @@ public:
/// @brief Merges newOpts into baseOpts
static void UicMergeOptions(std::vector<std::string>& baseOpts,
std::vector<std::string> const& newOpts,
- bool isQt5);
+ bool isQt5OrLater);
/// @brief Merges newOpts into baseOpts
static void RccMergeOptions(std::vector<std::string>& baseOpts,
std::vector<std::string> const& newOpts,
- bool isQt5);
+ bool isQt5OrLater);
/** @class RccLister
* @brief Lists files in qrc resource files
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 77fe87e4c..f9e889a66 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -15,7 +15,6 @@
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProcessOutput.h"
-#include "cmProperty.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenInitializer.h"
#include "cmState.h"
@@ -23,6 +22,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
cmQtAutoGenGlobalInitializer::Keywords::Keywords()
: AUTOMOC("AUTOMOC")
@@ -183,10 +183,10 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
// Set FOLDER property in the target
{
- cmProp folder =
+ cmValue folder =
makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
if (folder) {
- target->SetProperty("FOLDER", *folder);
+ target->SetProperty("FOLDER", folder);
}
}
}
diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h
index afcb4a2a9..3de5c1a85 100644
--- a/Source/cmQtAutoGenGlobalInitializer.h
+++ b/Source/cmQtAutoGenGlobalInitializer.h
@@ -49,7 +49,7 @@ public:
std::vector<std::unique_ptr<cmLocalGenerator>> const& localGenerators);
~cmQtAutoGenGlobalInitializer();
- Keywords const& kw() const { return this->Keywords_; };
+ Keywords const& kw() const { return this->Keywords_; }
bool generate();
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 4e3c58421..c49cafee5 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -24,6 +24,7 @@
#include "cmsys/SystemInformation.hxx"
+#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratedFileStream.h"
@@ -36,7 +37,6 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenGlobalInitializer.h"
#include "cmSourceFile.h"
@@ -47,6 +47,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -355,7 +356,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Targets FOLDER
{
- cmProp folder =
+ cmValue folder =
this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
if (!folder) {
folder = this->Makefile->GetState()->GetGlobalProperty(
@@ -522,6 +523,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
// Filters
cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),
this->Moc.MacroNames);
+ this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),
+ this->Moc.MacroNames.end());
{
auto filterList = cmExpandedList(
this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
@@ -1796,7 +1799,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP"
};
for (std::string const& prop : props) {
- cmProp propName = this->Makefile->GetState()->GetGlobalProperty(prop);
+ cmValue propName = this->Makefile->GetState()->GetGlobalProperty(prop);
if (cmNonempty(propName)) {
groupName = *propName;
property = prop;
@@ -1926,7 +1929,7 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target,
}
return 0u;
};
- auto toUInt2 = [](cmProp input) -> unsigned int {
+ auto toUInt2 = [](cmValue input) -> unsigned int {
unsigned long tmp = 0;
if (input && cmStrToULong(*input, &tmp)) {
return static_cast<unsigned int>(tmp);
@@ -1954,8 +1957,8 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target,
knownQtVersions.reserve(keys.size() * 2);
// Adds a version to the result (nullptr safe)
- auto addVersion = [&knownQtVersions, &toUInt2](cmProp major,
- cmProp minor) {
+ auto addVersion = [&knownQtVersions, &toUInt2](cmValue major,
+ cmValue minor) {
cmQtAutoGen::IntegerVersion ver(toUInt2(major), toUInt2(minor));
if (ver.Major != 0) {
knownQtVersions.emplace_back(ver);
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index e76817b9c..603c53777 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -95,7 +95,9 @@ public:
GenVarsT(GenT gen)
: Gen(gen)
- , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
+ , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen))
+ {
+ }
};
/** @param mocExecutable The file path to the moc executable. Will be used as
@@ -209,7 +211,9 @@ private:
struct MocT : public GenVarsT
{
MocT()
- : GenVarsT(GenT::MOC){};
+ : GenVarsT(GenT::MOC)
+ {
+ }
bool RelaxedMode = false;
bool PathPrefix = false;
@@ -237,7 +241,9 @@ private:
using UiFileT = std::pair<std::string, std::vector<std::string>>;
UicT()
- : GenVarsT(GenT::UIC){};
+ : GenVarsT(GenT::UIC)
+ {
+ }
std::set<std::string> SkipUi;
std::vector<std::string> UiFilesNoOptions;
@@ -252,7 +258,9 @@ private:
struct RccT : public GenVarsT
{
RccT()
- : GenVarsT(GenT::RCC){};
+ : GenVarsT(GenT::RCC)
+ {
+ }
bool GlobalTarget = false;
std::vector<Qrc> Qrcs;
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 568926e3c..e5c7bda66 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmQtAutoGenerator::Logger::Logger()
{
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 2753fd57c..4ed728ea9 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -310,7 +310,7 @@ public:
cmQtAutoMocUicT* Gen() const
{
return static_cast<cmQtAutoMocUicT*>(this->UserData());
- };
+ }
// -- Accessors. Only valid during Process() call!
Logger const& Log() const { return this->Gen()->Log(); }
@@ -346,7 +346,7 @@ public:
: JobT(true)
{
}
- void Process() override{};
+ void Process() override {}
};
/** Generate moc_predefs.h. */
@@ -2083,7 +2083,7 @@ void cmQtAutoMocUicT::JobCompileUicT::Process()
auto optionIt = this->UicConst().UiFiles.find(sourceFile);
if (optionIt != this->UicConst().UiFiles.end()) {
UicMergeOptions(allOpts, optionIt->second.Options,
- (this->BaseConst().QtVersion.Major == 5));
+ (this->BaseConst().QtVersion.Major >= 5));
}
cm::append(cmd, allOpts);
}
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index fce6e80bf..1e4dedde3 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -35,6 +35,7 @@ cmRST::cmRST(std::ostream& os, std::string docroot)
, TocTreeDirective("^.. toctree::[ \t]*(.*)$")
, ProductionListDirective("^.. productionlist::[ \t]*(.*)$")
, NoteDirective("^.. note::[ \t]*(.*)$")
+ , VersionDirective("^.. version(added|changed)::[ \t]*(.*)$")
, ModuleRST(R"(^#\[(=*)\[\.rst:$)")
, CMakeRole("(:cmake)?:("
"command|cpack_gen|generator|genex|"
@@ -209,6 +210,10 @@ void cmRST::ProcessLine(std::string const& line)
} else if (this->NoteDirective.find(line)) {
// Output note directives and their content normally.
this->NormalLine(line);
+ } else if (this->VersionDirective.find(line)) {
+ // Output versionadded and versionchanged directives and their content
+ // normally.
+ this->NormalLine(line);
}
}
// An explicit markup start followed nothing but whitespace and a
diff --git a/Source/cmRST.h b/Source/cmRST.h
index 17cdfe896..156b20a1b 100644
--- a/Source/cmRST.h
+++ b/Source/cmRST.h
@@ -83,6 +83,7 @@ private:
cmsys::RegularExpression TocTreeDirective;
cmsys::RegularExpression ProductionListDirective;
cmsys::RegularExpression NoteDirective;
+ cmsys::RegularExpression VersionDirective;
cmsys::RegularExpression ModuleRST;
cmsys::RegularExpression CMakeRole;
cmsys::RegularExpression InlineLink;
diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx
index 13455886b..8af13ae2b 100644
--- a/Source/cmRemoveCommand.cxx
+++ b/Source/cmRemoveCommand.cxx
@@ -4,8 +4,8 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
// cmRemoveCommand
bool cmRemoveCommand(std::vector<std::string> const& args,
@@ -17,7 +17,7 @@ bool cmRemoveCommand(std::vector<std::string> const& args,
std::string const& variable = args[0]; // VAR is always first
// get the old value
- cmProp cacheValue = status.GetMakefile().GetDefinition(variable);
+ cmValue cacheValue = status.GetMakefile().GetDefinition(variable);
// if there is no old value then return
if (!cacheValue) {
diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx
index 4dfdfae4f..26f255da0 100644
--- a/Source/cmRuntimeDependencyArchive.cxx
+++ b/Source/cmRuntimeDependencyArchive.cxx
@@ -236,7 +236,6 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
// Add newer Visual Studio paths
- AddVisualStudioPath(paths, "Visual Studio 17 ", 17, gg);
AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index a58be621c..1bb459c4b 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -8,9 +8,9 @@
#include "cmFindCommon.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
: FC(findCmd)
@@ -78,7 +78,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable)
assert(this->FC != nullptr);
// Get a path from a CMake variable.
- if (cmProp value = this->FC->Makefile->GetDefinition(variable)) {
+ if (cmValue value = this->FC->Makefile->GetDefinition(variable)) {
std::vector<std::string> expanded = cmExpandedList(*value);
for (std::string const& p : expanded) {
@@ -102,7 +102,7 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable)
assert(this->FC != nullptr);
// Get a path from a CMake variable.
- if (cmProp value = this->FC->Makefile->GetDefinition(variable)) {
+ if (cmValue value = this->FC->Makefile->GetDefinition(variable)) {
std::vector<std::string> expanded = cmExpandedList(*value);
this->AddPrefixPaths(
@@ -179,7 +179,7 @@ void cmSearchPath::AddPrefixPaths(const std::vector<std::string>& paths,
dir += "/";
}
if (subdir == "include" || subdir == "lib") {
- cmProp arch =
+ cmValue arch =
this->FC->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
if (cmNonempty(arch)) {
if (this->FC->Makefile->IsDefinitionSet("CMAKE_SYSROOT") &&
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index 52b1a4431..17285e723 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -4,15 +4,16 @@
#include <algorithm>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmArgumentParser.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmSeparateArgumentsCommand
bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
@@ -27,7 +28,7 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
if (args.size() == 1) {
// Original space-replacement version of command.
- if (cmProp def = status.GetMakefile().GetDefinition(var)) {
+ if (cmValue def = status.GetMakefile().GetDefinition(var)) {
std::string value = *def;
std::replace(value.begin(), value.end(), ' ', ';');
status.GetMakefile().AddDefinition(var, value);
@@ -81,7 +82,7 @@ bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
}
if (unparsedArguments.empty()) {
- status.GetMakefile().AddDefinition(var, {});
+ status.GetMakefile().AddDefinition(var, cm::string_view{});
return true;
}
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 354b4c327..ce0cb258c 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -5,12 +5,12 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmSetCommand
bool cmSetCommand(std::vector<std::string> const& args,
@@ -136,7 +136,7 @@ bool cmSetCommand(std::vector<std::string> const& args,
// see if this is already in the cache
cmState* state = status.GetMakefile().GetState();
- cmProp existingValue = state->GetCacheEntryValue(variable);
+ cmValue existingValue = state->GetCacheEntryValue(variable);
if (existingValue &&
(state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) {
// if the set is trying to CACHE the value but the value
diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx
index 07ad24602..9adf5373b 100644
--- a/Source/cmSetDirectoryPropertiesCommand.cxx
+++ b/Source/cmSetDirectoryPropertiesCommand.cxx
@@ -32,7 +32,7 @@ bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args,
"Commands and macros cannot be set using SET_CMAKE_PROPERTIES");
return false;
}
- status.GetMakefile().SetProperty(prop, (iter + 1)->c_str());
+ status.GetMakefile().SetProperty(prop, *(iter + 1));
}
return true;
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index c8990537b..db10cd47a 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -21,6 +21,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -116,7 +117,7 @@ bool HandleSourceFileDirectoryScopes(
"given non-existent target for TARGET_DIRECTORY ", target_name));
return false;
}
- cmProp target_source_dir = target->GetProperty("BINARY_DIR");
+ cmValue target_source_dir = target->GetProperty("BINARY_DIR");
cmMakefile* target_dir_mf =
status.GetMakefile().GetGlobalGenerator()->FindMakefile(
*target_source_dir);
@@ -294,7 +295,7 @@ bool HandleAndValidateSourceFilePropertyGENERATED(
sf->SetProperty("GENERATED", nullptr);
break;
case PropertyOp::Set:
- sf->SetProperty("GENERATED", propertyValue.c_str());
+ sf->SetProperty("GENERATED", propertyValue);
break;
}
} else {
@@ -474,7 +475,7 @@ bool HandleGlobalMode(cmExecutionStatus& status,
if (remove) {
cm->SetProperty(propertyName, nullptr);
} else {
- cm->SetProperty(propertyName, propertyValue.c_str());
+ cm->SetProperty(propertyName, propertyValue);
}
}
@@ -520,7 +521,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status,
if (remove) {
mf->SetProperty(propertyName, nullptr);
} else {
- mf->SetProperty(propertyName, propertyValue.c_str());
+ mf->SetProperty(propertyName, propertyValue);
}
}
@@ -631,7 +632,7 @@ bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
if (remove) {
sf->SetProperty(propertyName, nullptr);
} else {
- sf->SetProperty(propertyName, propertyValue.c_str());
+ sf->SetProperty(propertyName, propertyValue);
}
}
return true;
@@ -681,7 +682,7 @@ bool HandleTest(cmTest* test, const std::string& propertyName,
if (remove) {
test->SetProperty(propertyName, nullptr);
} else {
- test->SetProperty(propertyName, propertyValue.c_str());
+ test->SetProperty(propertyName, propertyValue);
}
}
@@ -719,7 +720,7 @@ bool HandleCacheMode(cmExecutionStatus& status,
for (std::string const& name : names) {
// Get the source file.
cmake* cm = status.GetMakefile().GetCMakeInstance();
- cmProp existingValue = cm->GetState()->GetCacheEntryValue(name);
+ cmValue existingValue = cm->GetState()->GetCacheEntryValue(name);
if (existingValue) {
if (!HandleCacheEntry(name, status.GetMakefile(), propertyName,
propertyValue, appendAsString, appendMode,
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index 237b67fed..ab93ddb54 100644
--- a/Source/cmSetSourceFilesPropertiesCommand.cxx
+++ b/Source/cmSetSourceFilesPropertiesCommand.cxx
@@ -173,7 +173,7 @@ static bool RunCommandForScope(
SetPropertyCommand::HandleAndValidateSourceFilePropertyGENERATED(
sf, *(k + 1));
} else {
- sf->SetProperty(*k, (k + 1)->c_str());
+ sf->SetProperty(*k, *(k + 1));
}
}
}
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index c4bff76f6..a17c96451 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -37,7 +37,7 @@ bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args,
// loop through all the props and set them
for (auto k = propsIter + 1; k != args.end(); k += 2) {
if (!k->empty()) {
- test->SetProperty(*k, (k + 1)->c_str());
+ test->SetProperty(*k, *(k + 1));
}
}
} else {
diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx
index 58af8f0b0..61d1c3002 100644
--- a/Source/cmSiteNameCommand.cxx
+++ b/Source/cmSiteNameCommand.cxx
@@ -6,10 +6,9 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
-#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmSiteNameCommand
bool cmSiteNameCommand(std::vector<std::string> const& args,
@@ -27,12 +26,12 @@ bool cmSiteNameCommand(std::vector<std::string> const& args,
paths.emplace_back("/sbin");
paths.emplace_back("/usr/local/bin");
- cmProp cacheValue = status.GetMakefile().GetDefinition(args[0]);
+ cmValue cacheValue = status.GetMakefile().GetDefinition(args[0]);
if (cacheValue) {
return true;
}
- cmProp temp = status.GetMakefile().GetDefinition("HOSTNAME");
+ cmValue temp = status.GetMakefile().GetDefinition("HOSTNAME");
std::string hostname_cmd;
if (temp) {
hostname_cmd = *temp;
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 3f3c8d501..3fa0051e2 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -13,6 +13,7 @@
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name,
@@ -53,7 +54,7 @@ std::string cmSourceFile::GetObjectLibrary() const
std::string const& cmSourceFile::GetOrDetermineLanguage()
{
// If the language was set explicitly by the user then use it.
- if (cmProp lang = this->GetProperty(propLANGUAGE)) {
+ if (cmValue lang = this->GetProperty(propLANGUAGE)) {
// Assign to member in order to return a reference.
this->Language = *lang;
return this->Language;
@@ -84,7 +85,7 @@ std::string const& cmSourceFile::GetOrDetermineLanguage()
std::string cmSourceFile::GetLanguage() const
{
// If the language was set explicitly by the user then use it.
- if (cmProp lang = this->GetProperty(propLANGUAGE)) {
+ if (cmValue lang = this->GetProperty(propLANGUAGE)) {
return *lang;
}
@@ -269,7 +270,8 @@ bool cmSourceFile::Matches(cmSourceFileLocation const& loc)
return this->Location.Matches(loc);
}
-void cmSourceFile::SetProperty(const std::string& prop, const char* value)
+template <typename ValueType>
+void cmSourceFile::StoreProperty(const std::string& prop, ValueType value)
{
if (prop == propINCLUDE_DIRECTORIES) {
this->IncludeDirectories.clear();
@@ -294,6 +296,15 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value)
}
}
+void cmSourceFile::SetProperty(const std::string& prop, const char* value)
+{
+ this->StoreProperty(prop, value);
+}
+void cmSourceFile::SetProperty(const std::string& prop, cmValue value)
+{
+ this->StoreProperty(prop, value);
+}
+
void cmSourceFile::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
{
@@ -317,7 +328,7 @@ void cmSourceFile::AppendProperty(const std::string& prop,
}
}
-cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
+cmValue cmSourceFile::GetPropertyForUser(const std::string& prop)
{
// This method is a consequence of design history and backwards
// compatibility. GetProperty is (and should be) a const method.
@@ -342,7 +353,7 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
// if it is requested by the user.
if (prop == propLANGUAGE) {
// The pointer is valid until `this->Language` is modified.
- return &this->GetOrDetermineLanguage();
+ return cmValue(this->GetOrDetermineLanguage());
}
// Special handling for GENERATED property.
@@ -355,23 +366,23 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
(policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)
? CheckScope::GlobalAndLocal
: CheckScope::Global)) {
- return &propTRUE;
+ return cmValue(propTRUE);
}
- return &propFALSE;
+ return cmValue(propFALSE);
}
// Perform the normal property lookup.
return this->GetProperty(prop);
}
-cmProp cmSourceFile::GetProperty(const std::string& prop) const
+cmValue cmSourceFile::GetProperty(const std::string& prop) const
{
// Check for computed properties.
if (prop == propLOCATION) {
if (this->FullPath.empty()) {
return nullptr;
}
- return &this->FullPath;
+ return cmValue(this->FullPath);
}
// Check for the properties with backtraces.
@@ -382,7 +393,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->IncludeDirectories, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propCOMPILE_OPTIONS) {
@@ -392,7 +403,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileOptions, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
@@ -402,10 +413,10 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileDefinitions, ";");
- return &output;
+ return cmValue(output);
}
- cmProp retVal = this->Properties.GetPropertyValue(prop);
+ cmValue retVal = this->Properties.GetPropertyValue(prop);
if (!retVal) {
cmMakefile const* mf = this->Location.GetMakefile();
const bool chain =
@@ -421,7 +432,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
const std::string& cmSourceFile::GetSafeProperty(const std::string& prop) const
{
- cmProp ret = this->GetProperty(prop);
+ cmValue ret = this->GetProperty(prop);
if (ret) {
return *ret;
}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 32ed68715..c1c52010c 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -10,10 +10,10 @@
#include "cmCustomCommand.h"
#include "cmListFileCache.h"
-#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
+#include "cmValue.h"
class cmMakefile;
@@ -42,17 +42,22 @@ public:
//! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmValue(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
//! Might return a nullptr if the property is not set or invalid
- cmProp GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop) const;
//! Always returns a valid pointer
const std::string& GetSafeProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
/** Implement getting a property when called from a CMake language
command like get_property or get_source_file_property. */
- cmProp GetPropertyForUser(const std::string& prop);
+ cmValue GetPropertyForUser(const std::string& prop);
/// Marks this file as generated
/**
@@ -145,6 +150,9 @@ public:
std::string GetObjectLibrary() const;
private:
+ template <typename ValueType>
+ void StoreProperty(const std::string& prop, ValueType value);
+
cmSourceFileLocation Location;
cmPropertyMap Properties;
std::unique_ptr<cmCustomCommand> CustomCommand;
diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx
index 37ed4c130..61416e063 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -20,9 +20,10 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
+#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -57,10 +58,10 @@ int ParseStd(std::string const& level)
return -1;
}
-struct StanardLevelComputer
+struct StandardLevelComputer
{
- explicit StanardLevelComputer(std::string lang, std::vector<int> levels,
- std::vector<std::string> levelsStr)
+ explicit StandardLevelComputer(std::string lang, std::vector<int> levels,
+ std::vector<std::string> levelsStr)
: Language(std::move(lang))
, Levels(std::move(levels))
, LevelsAsStrings(std::move(levelsStr))
@@ -76,37 +77,74 @@ struct StanardLevelComputer
const auto& stds = this->Levels;
const auto& stdsStrings = this->LevelsAsStrings;
- cmProp defaultStd = makefile->GetDefinition(
+ cmValue defaultStd = makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
if (!cmNonempty(defaultStd)) {
// this compiler has no notion of language standard levels
return std::string{};
}
+ cmPolicies::PolicyStatus const cmp0128{ makefile->GetPolicyStatus(
+ cmPolicies::CMP0128) };
+ bool const defaultExt{ cmIsOn(*makefile->GetDefinition(
+ cmStrCat("CMAKE_", this->Language, "_EXTENSIONS_DEFAULT"))) };
bool ext = true;
- if (cmProp extPropValue = target->GetLanguageExtensions(this->Language)) {
- if (cmIsOff(*extPropValue)) {
- ext = false;
- }
+
+ if (cmp0128 == cmPolicies::NEW) {
+ ext = defaultExt;
}
- cmProp standardProp = target->GetLanguageStandard(this->Language, config);
+ if (cmValue extPropValue = target->GetLanguageExtensions(this->Language)) {
+ ext = cmIsOn(*extPropValue);
+ }
+
+ std::string const type{ ext ? "EXTENSION" : "STANDARD" };
+
+ cmValue standardProp = target->GetLanguageStandard(this->Language, config);
if (!standardProp) {
- if (ext) {
- // No language standard is specified and extensions are not disabled.
- // Check if this compiler needs a flag to enable extensions.
- return cmStrCat("CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION");
+ if (cmp0128 == cmPolicies::NEW) {
+ // Add extension flag if compiler's default doesn't match.
+ if (ext != defaultExt) {
+ return cmStrCat("CMAKE_", this->Language, *defaultStd, "_", type,
+ "_COMPILE_OPTION");
+ }
+ } else {
+ if (cmp0128 == cmPolicies::WARN &&
+ makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0128") &&
+ ext != defaultExt) {
+ const char* state{};
+ if (ext) {
+ if (!makefile->GetDefinition(cmStrCat(
+ "CMAKE_", this->Language, "_EXTENSION_COMPILE_OPTION"))) {
+ state = "enabled";
+ }
+ } else {
+ state = "disabled";
+ }
+ if (state) {
+ makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0128),
+ "\nFor compatibility with older versions of CMake, "
+ "compiler extensions won't be ",
+ state, "."));
+ }
+ }
+
+ if (ext) {
+ return cmStrCat("CMAKE_", this->Language,
+ "_EXTENSION_COMPILE_OPTION");
+ }
}
return std::string{};
}
- std::string const type = ext ? "EXTENSION" : "STANDARD";
-
if (target->GetLanguageStandardRequired(this->Language)) {
std::string option_flag = cmStrCat(
"CMAKE_", this->Language, *standardProp, "_", type, "_COMPILE_OPTION");
- cmProp opt = target->Target->GetMakefile()->GetDefinition(option_flag);
+ cmValue opt = target->Target->GetMakefile()->GetDefinition(option_flag);
if (!opt) {
std::ostringstream e;
e << "Target \"" << target->GetName()
@@ -121,6 +159,25 @@ struct StanardLevelComputer
return option_flag;
}
+ // If the request matches the compiler's defaults we don't need to add
+ // anything.
+ if (*standardProp == *defaultStd && ext == defaultExt) {
+ if (cmp0128 == cmPolicies::NEW) {
+ return std::string{};
+ }
+
+ if (cmp0128 == cmPolicies::WARN &&
+ makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0128")) {
+ makefile->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0128),
+ "\nFor compatibility with older versions of CMake, "
+ "unnecessary flags for language standard or compiler "
+ "extensions may be added."));
+ }
+ }
+
std::string standardStr(*standardProp);
if (this->Language == "CUDA" && standardStr == "98") {
standardStr = "03";
@@ -147,17 +204,18 @@ struct StanardLevelComputer
return std::string{};
}
- // If the standard requested is older than the compiler's default
- // then we need to use a flag to change it.
- if (stdIt <= defaultStdIt) {
+ // If the standard requested is older than the compiler's default or the
+ // extension mode doesn't match then we need to use a flag.
+ if (stdIt < defaultStdIt ||
+ (cmp0128 == cmPolicies::NEW && ext != defaultExt)) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
return cmStrCat("CMAKE_", this->Language, stdsStrings[offset], "_", type,
"_COMPILE_OPTION");
}
- // The standard requested is at least as new as the compiler's default,
- // and the standard request is not required. Decay to the newest standard
- // for which a flag is defined.
+ // The compiler's default is at least as new as the requested standard,
+ // and the requested standard is not required. Decay to the newest
+ // standard for which a flag is defined.
for (; defaultStdIt < stdIt; --stdIt) {
auto offset = std::distance(cm::cbegin(stds), stdIt);
std::string option_flag =
@@ -174,7 +232,7 @@ struct StanardLevelComputer
bool GetNewRequiredStandard(cmMakefile* makefile,
std::string const& targetName,
const std::string& feature,
- cmProp currentLangStandardValue,
+ cmValue currentLangStandardValue,
std::string& newRequiredStandard,
std::string* error) const
{
@@ -186,9 +244,9 @@ struct StanardLevelComputer
auto needed = this->HighestStandardNeeded(makefile, feature);
- cmProp existingStandard = currentLangStandardValue;
+ cmValue existingStandard = currentLangStandardValue;
if (!existingStandard) {
- cmProp defaultStandard = makefile->GetDefinition(
+ cmValue defaultStandard = makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
if (cmNonempty(defaultStandard)) {
existingStandard = defaultStandard;
@@ -231,7 +289,7 @@ struct StanardLevelComputer
std::string const& config,
std::string const& feature) const
{
- cmProp defaultStandard = makefile->GetDefinition(
+ cmValue defaultStandard = makefile->GetDefinition(
cmStrCat("CMAKE_", this->Language, "_STANDARD_DEFAULT"));
if (!defaultStandard) {
makefile->IssueMessage(
@@ -253,7 +311,7 @@ struct StanardLevelComputer
return false;
}
- cmProp existingStandard =
+ cmValue existingStandard =
target->GetLanguageStandard(this->Language, config);
if (!existingStandard) {
existingStandard = defaultStandard;
@@ -283,7 +341,7 @@ struct StanardLevelComputer
std::string prefix = cmStrCat("CMAKE_", this->Language);
StandardNeeded maxLevel = { -1, -1 };
for (size_t i = 0; i < this->Levels.size(); ++i) {
- if (cmProp prop = makefile->GetDefinition(
+ if (cmValue prop = makefile->GetDefinition(
cmStrCat(prefix, this->LevelsAsStrings[i], "_COMPILE_FEATURES"))) {
std::vector<std::string> props = cmExpandedList(*prop);
if (cm::contains(props, feature)) {
@@ -308,31 +366,33 @@ struct StanardLevelComputer
std::vector<std::string> LevelsAsStrings;
};
-std::unordered_map<std::string, StanardLevelComputer> StandardComputerMapping =
- { { "C",
- StanardLevelComputer{
+std::unordered_map<std::string, StandardLevelComputer>
+ StandardComputerMapping = {
+ { "C",
+ StandardLevelComputer{
"C", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "CXX",
- StanardLevelComputer{
+ StandardLevelComputer{
"CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
{ "CUDA",
- StanardLevelComputer{
+ StandardLevelComputer{
"CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } },
{ "OBJC",
- StanardLevelComputer{
+ StandardLevelComputer{
"OBJC", std::vector<int>{ 90, 99, 11, 17, 23 },
std::vector<std::string>{ "90", "99", "11", "17", "23" } } },
{ "OBJCXX",
- StanardLevelComputer{
+ StandardLevelComputer{
"OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } },
{ "HIP",
- StanardLevelComputer{
+ StandardLevelComputer{
"HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 },
- std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } };
+ std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }
+ };
}
std::string cmStandardLevelResolver::GetCompileOptionDef(
@@ -387,7 +447,11 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
return false;
}
- const char* features = this->CompileFeaturesAvailable(lang, error);
+ if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
+ return true;
+ }
+
+ cmValue features = this->CompileFeaturesAvailable(lang, error);
if (!features) {
return false;
}
@@ -465,7 +529,7 @@ bool cmStandardLevelResolver::CompileFeatureKnown(
return false;
}
-const char* cmStandardLevelResolver::CompileFeaturesAvailable(
+cmValue cmStandardLevelResolver::CompileFeaturesAvailable(
const std::string& lang, std::string* error) const
{
if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
@@ -484,7 +548,7 @@ const char* cmStandardLevelResolver::CompileFeaturesAvailable(
return nullptr;
}
- cmProp featuresKnown =
+ cmValue featuresKnown =
this->Makefile->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
if (!cmNonempty(featuresKnown)) {
@@ -507,12 +571,12 @@ const char* cmStandardLevelResolver::CompileFeaturesAvailable(
}
return nullptr;
}
- return cmToCStr(featuresKnown);
+ return featuresKnown;
}
bool cmStandardLevelResolver::GetNewRequiredStandard(
const std::string& targetName, const std::string& feature,
- cmProp currentLangStandardValue, std::string& newRequiredStandard,
+ cmValue currentLangStandardValue, std::string& newRequiredStandard,
std::string* error) const
{
std::string lang;
diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h
index d84fbcbe1..422645604 100644
--- a/Source/cmStandardLevelResolver.h
+++ b/Source/cmStandardLevelResolver.h
@@ -4,7 +4,7 @@
#include <string>
-#include "cmProperty.h"
+#include "cmValue.h"
class cmMakefile;
class cmGeneratorTarget;
@@ -30,12 +30,12 @@ public:
const std::string& feature, std::string& lang,
std::string* error) const;
- const char* CompileFeaturesAvailable(const std::string& lang,
- std::string* error) const;
+ cmValue CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const;
bool GetNewRequiredStandard(const std::string& targetName,
const std::string& feature,
- cmProp currentLangStandardValue,
+ cmValue currentLangStandardValue,
std::string& newRequiredStandard,
std::string* error = nullptr) const;
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index ce6eb311e..e79949d97 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -26,7 +26,9 @@
#include "cmSystemTools.h"
#include "cmake.h"
-cmState::cmState()
+cmState::cmState(Mode mode, ProjectKind projectKind)
+ : StateMode(mode)
+ , StateProjectKind(projectKind)
{
this->CacheManager = cm::make_unique<cmCacheManager>();
this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>();
@@ -142,20 +144,20 @@ std::vector<std::string> cmState::GetCacheEntryKeys() const
return this->CacheManager->GetCacheEntryKeys();
}
-cmProp cmState::GetCacheEntryValue(std::string const& key) const
+cmValue cmState::GetCacheEntryValue(std::string const& key) const
{
return this->CacheManager->GetCacheEntryValue(key);
}
std::string cmState::GetSafeCacheEntryValue(std::string const& key) const
{
- if (cmProp val = this->GetCacheEntryValue(key)) {
+ if (cmValue val = this->GetCacheEntryValue(key)) {
return *val;
}
return std::string();
}
-cmProp cmState::GetInitializedCacheValue(std::string const& key) const
+cmValue cmState::GetInitializedCacheValue(std::string const& key) const
{
return this->CacheManager->GetInitializedCacheValue(key);
}
@@ -192,8 +194,8 @@ std::vector<std::string> cmState::GetCacheEntryPropertyList(
return this->CacheManager->GetCacheEntryPropertyList(key);
}
-cmProp cmState::GetCacheEntryProperty(std::string const& key,
- std::string const& propertyName)
+cmValue cmState::GetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName)
{
return this->CacheManager->GetCacheEntryProperty(key, propertyName);
}
@@ -204,7 +206,7 @@ bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
return this->CacheManager->GetCacheEntryPropertyAsBool(key, propertyName);
}
-void cmState::AddCacheEntry(const std::string& key, const char* value,
+void cmState::AddCacheEntry(const std::string& key, cmValue value,
const char* helpString,
cmStateEnums::CacheEntryType type)
{
@@ -275,15 +277,10 @@ cmStateSnapshot cmState::Reset()
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it =
this->BuildsystemDirectory.Truncate();
it->IncludeDirectories.clear();
- it->IncludeDirectoryBacktraces.clear();
it->CompileDefinitions.clear();
- it->CompileDefinitionsBacktraces.clear();
it->CompileOptions.clear();
- it->CompileOptionsBacktraces.clear();
it->LinkOptions.clear();
- it->LinkOptionsBacktraces.clear();
it->LinkDirectories.clear();
- it->LinkDirectoriesBacktraces.clear();
it->DirectoryEnd = pos;
it->NormalTargetNames.clear();
it->ImportedTargetNames.clear();
@@ -381,16 +378,6 @@ void cmState::ClearEnabledLanguages()
this->EnabledLanguages.clear();
}
-bool cmState::GetIsInTryCompile() const
-{
- return this->IsInTryCompile;
-}
-
-void cmState::SetIsInTryCompile(bool b)
-{
- this->IsInTryCompile = b;
-}
-
bool cmState::GetIsGeneratorMultiConfig() const
{
return this->IsGeneratorMultiConfig;
@@ -466,7 +453,7 @@ void cmState::AddDisallowedCommand(std::string const& name,
case cmPolicies::WARN:
mf.IssueMessage(MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(policy));
- break;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_IF_USED:
@@ -485,7 +472,7 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error)
name,
[name, error](std::vector<cmListFileArgument> const&,
cmExecutionStatus& status) -> bool {
- cmProp versionValue =
+ cmValue versionValue =
status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
if (name == "endif" &&
(!versionValue || atof(versionValue->c_str()) <= 1.4)) {
@@ -577,6 +564,10 @@ void cmState::SetGlobalProperty(const std::string& prop, const char* value)
{
this->GlobalProperties.SetProperty(prop, value);
}
+void cmState::SetGlobalProperty(const std::string& prop, cmValue value)
+{
+ this->GlobalProperties.SetProperty(prop, value);
+}
void cmState::AppendGlobalProperty(const std::string& prop,
const std::string& value, bool asString)
@@ -584,7 +575,7 @@ void cmState::AppendGlobalProperty(const std::string& prop,
this->GlobalProperties.AppendProperty(prop, value, asString);
}
-cmProp cmState::GetGlobalProperty(const std::string& prop)
+cmValue cmState::GetGlobalProperty(const std::string& prop)
{
if (prop == "CACHE_VARIABLES") {
std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
@@ -593,8 +584,9 @@ cmProp cmState::GetGlobalProperty(const std::string& prop)
std::vector<std::string> commands = this->GetCommandNames();
this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
} else if (prop == "IN_TRY_COMPILE") {
- this->SetGlobalProperty("IN_TRY_COMPILE",
- this->IsInTryCompile ? "1" : "0");
+ this->SetGlobalProperty(
+ "IN_TRY_COMPILE",
+ this->StateProjectKind == ProjectKind::TryCompile ? "1" : "0");
} else if (prop == "GENERATOR_IS_MULTI_CONFIG") {
this->SetGlobalProperty("GENERATOR_IS_MULTI_CONFIG",
this->IsGeneratorMultiConfig ? "1" : "0");
@@ -610,47 +602,47 @@ cmProp cmState::GetGlobalProperty(const std::string& prop)
if (prop == "CMAKE_C_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_C90_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C90_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_C99_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C99_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_C11_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_C11_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_CXX98_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX98_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_CXX11_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX11_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_CXX14_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CXX14_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
if (prop == "CMAKE_CUDA_KNOWN_FEATURES") {
static const std::string s_out(
&FOR_EACH_CUDA_FEATURE(STRING_LIST_ELEMENT)[1]);
- return &s_out;
+ return cmValue(s_out);
}
#undef STRING_LIST_ELEMENT
@@ -771,17 +763,12 @@ unsigned int cmState::GetCacheMinorVersion() const
cmState::Mode cmState::GetMode() const
{
- return this->CurrentMode;
+ return this->StateMode;
}
std::string cmState::GetModeString() const
{
- return ModeToString(this->CurrentMode);
-}
-
-void cmState::SetMode(cmState::Mode mode)
-{
- this->CurrentMode = mode;
+ return ModeToString(this->StateMode);
}
std::string cmState::ModeToString(cmState::Mode mode)
@@ -803,6 +790,11 @@ std::string cmState::ModeToString(cmState::Mode mode)
return "UNKNOWN";
}
+cmState::ProjectKind cmState::GetProjectKind() const
+{
+ return this->StateProjectKind;
+}
+
std::string const& cmState::GetBinaryDirectory() const
{
return this->BinaryDirectory;
diff --git a/Source/cmState.h b/Source/cmState.h
index 9951b9acf..a1666ca1f 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -21,6 +21,7 @@
#include "cmPropertyMap.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
class cmCacheManager;
class cmCommand;
@@ -35,12 +36,6 @@ class cmState
friend class cmStateSnapshot;
public:
- cmState();
- ~cmState();
-
- cmState(const cmState&) = delete;
- cmState& operator=(const cmState&) = delete;
-
enum Mode
{
Unknown,
@@ -51,6 +46,18 @@ public:
CPack,
};
+ enum class ProjectKind
+ {
+ Normal,
+ TryCompile,
+ };
+
+ cmState(Mode mode, ProjectKind projectKind = ProjectKind::Normal);
+ ~cmState();
+
+ cmState(const cmState&) = delete;
+ cmState& operator=(const cmState&) = delete;
+
static const std::string& GetTargetTypeName(
cmStateEnums::TargetType targetType);
@@ -92,9 +99,9 @@ public:
bool IsCacheLoaded() const;
std::vector<std::string> GetCacheEntryKeys() const;
- cmProp GetCacheEntryValue(std::string const& key) const;
+ cmValue GetCacheEntryValue(std::string const& key) const;
std::string GetSafeCacheEntryValue(std::string const& key) const;
- cmProp GetInitializedCacheValue(std::string const& key) const;
+ cmValue GetInitializedCacheValue(std::string const& key) const;
cmStateEnums::CacheEntryType GetCacheEntryType(std::string const& key) const;
void SetCacheEntryValue(std::string const& key, std::string const& value);
@@ -106,8 +113,8 @@ public:
void SetCacheEntryBoolProperty(std::string const& key,
std::string const& propertyName, bool value);
std::vector<std::string> GetCacheEntryPropertyList(std::string const& key);
- cmProp GetCacheEntryProperty(std::string const& key,
- std::string const& propertyName);
+ cmValue GetCacheEntryProperty(std::string const& key,
+ std::string const& propertyName);
bool GetCacheEntryPropertyAsBool(std::string const& key,
std::string const& propertyName);
void AppendCacheEntryProperty(std::string const& key,
@@ -141,9 +148,6 @@ public:
void SetEnabledLanguages(std::vector<std::string> const& langs);
void ClearEnabledLanguages();
- bool GetIsInTryCompile() const;
- void SetIsInTryCompile(bool b);
-
bool GetIsGeneratorMultiConfig() const;
void SetIsGeneratorMultiConfig(bool b);
@@ -175,9 +179,10 @@ public:
std::vector<std::string> GetCommandNames() const;
void SetGlobalProperty(const std::string& prop, const char* value);
+ void SetGlobalProperty(const std::string& prop, cmValue value);
void AppendGlobalProperty(const std::string& prop, const std::string& value,
bool asString = false);
- cmProp GetGlobalProperty(const std::string& prop);
+ cmValue GetGlobalProperty(const std::string& prop);
bool GetGlobalPropertyAsBool(const std::string& prop);
std::string const& GetSourceDirectory() const;
@@ -207,13 +212,26 @@ public:
Mode GetMode() const;
std::string GetModeString() const;
- void SetMode(Mode mode);
static std::string ModeToString(Mode mode);
+ ProjectKind GetProjectKind() const;
+
private:
friend class cmake;
void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key,
+ value ? cmValue(std::string(value)) : cmValue(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key, cmValue(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmValue value,
const char* helpString,
cmStateEnums::CacheEntryType type);
@@ -248,7 +266,6 @@ private:
std::string SourceDirectory;
std::string BinaryDirectory;
- bool IsInTryCompile = false;
bool IsGeneratorMultiConfig = false;
bool WindowsShell = false;
bool WindowsVSIDE = false;
@@ -258,5 +275,6 @@ private:
bool NMake = false;
bool MSYSShell = false;
bool NinjaMulti = false;
- Mode CurrentMode = Unknown;
+ Mode StateMode = Unknown;
+ ProjectKind StateProjectKind = ProjectKind::Normal;
};
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index c898dd475..b42e5c338 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -19,7 +19,9 @@
#include "cmState.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
static std::string const kBINARY_DIR = "BINARY_DIR";
static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS";
@@ -63,7 +65,7 @@ cmStateDirectory::cmStateDirectory(
}
template <typename T, typename U>
-cmStringRange GetPropertyContent(T const& content, U contentEndPosition)
+cmBTStringRange GetPropertyContent(T const& content, U contentEndPosition)
{
auto end = content.begin() + contentEndPosition;
@@ -73,88 +75,59 @@ cmStringRange GetPropertyContent(T const& content, U contentEndPosition)
return cmMakeRange(rbegin.base(), end);
}
-template <typename T, typename U, typename V>
-cmBacktraceRange GetPropertyBacktraces(T const& content, U const& backtraces,
- V contentEndPosition)
-{
- auto entryEnd = content.begin() + contentEndPosition;
-
- auto rbegin = cm::make_reverse_iterator(entryEnd);
- rbegin = std::find(rbegin, content.rend(), cmPropertySentinal);
-
- auto it = backtraces.begin() + std::distance(content.begin(), rbegin.base());
-
- auto end = backtraces.end();
- return cmMakeRange(it, end);
-}
-
-template <typename T, typename U, typename V>
-void AppendEntry(T& content, U& backtraces, V& endContentPosition,
- const std::string& value, const cmListFileBacktrace& lfbt)
+template <typename T, typename U>
+void AppendEntry(T& content, U& endContentPosition,
+ const BT<std::string>& value)
{
- if (value.empty()) {
+ if (value.Value.empty()) {
return;
}
assert(endContentPosition == content.size());
content.push_back(value);
- backtraces.push_back(lfbt);
endContentPosition = content.size();
}
-template <typename T, typename U, typename V>
-void SetContent(T& content, U& backtraces, V& endContentPosition,
- const std::string& vec, const cmListFileBacktrace& lfbt)
+template <typename T, typename U>
+void SetContent(T& content, U& endContentPosition, const BT<std::string>& vec)
{
assert(endContentPosition == content.size());
content.resize(content.size() + 2);
- backtraces.resize(backtraces.size() + 2);
content.back() = vec;
- backtraces.back() = lfbt;
endContentPosition = content.size();
}
-template <typename T, typename U, typename V>
-void ClearContent(T& content, U& backtraces, V& endContentPosition)
+template <typename T, typename U>
+void ClearContent(T& content, U& endContentPosition)
{
assert(endContentPosition == content.size());
content.resize(content.size() + 1);
- backtraces.resize(backtraces.size() + 1);
endContentPosition = content.size();
}
-cmStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const
+cmBTStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const
{
return GetPropertyContent(
this->DirectoryState->IncludeDirectories,
this->Snapshot_.Position->IncludeDirectoryPosition);
}
-cmBacktraceRange cmStateDirectory::GetIncludeDirectoriesEntryBacktraces() const
-{
- return GetPropertyBacktraces(
- this->DirectoryState->IncludeDirectories,
- this->DirectoryState->IncludeDirectoryBacktraces,
- this->Snapshot_.Position->IncludeDirectoryPosition);
-}
-
void cmStateDirectory::AppendIncludeDirectoriesEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+ const BT<std::string>& vec)
{
AppendEntry(this->DirectoryState->IncludeDirectories,
- this->DirectoryState->IncludeDirectoryBacktraces,
- this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt);
+ this->Snapshot_.Position->IncludeDirectoryPosition, vec);
}
void cmStateDirectory::PrependIncludeDirectoriesEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+ const BT<std::string>& vec)
{
auto entryEnd = this->DirectoryState->IncludeDirectories.begin() +
this->Snapshot_.Position->IncludeDirectoryPosition;
@@ -164,167 +137,111 @@ void cmStateDirectory::PrependIncludeDirectoriesEntry(
rbegin = std::find(rbegin, rend, cmPropertySentinal);
auto entryIt = rbegin.base();
- auto entryBegin = this->DirectoryState->IncludeDirectories.begin();
-
- auto btIt = this->DirectoryState->IncludeDirectoryBacktraces.begin() +
- std::distance(entryBegin, entryIt);
this->DirectoryState->IncludeDirectories.insert(entryIt, vec);
- this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt);
this->Snapshot_.Position->IncludeDirectoryPosition =
this->DirectoryState->IncludeDirectories.size();
}
-void cmStateDirectory::SetIncludeDirectories(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::SetIncludeDirectories(const BT<std::string>& vec)
{
SetContent(this->DirectoryState->IncludeDirectories,
- this->DirectoryState->IncludeDirectoryBacktraces,
- this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt);
+ this->Snapshot_.Position->IncludeDirectoryPosition, vec);
}
void cmStateDirectory::ClearIncludeDirectories()
{
ClearContent(this->DirectoryState->IncludeDirectories,
- this->DirectoryState->IncludeDirectoryBacktraces,
this->Snapshot_.Position->IncludeDirectoryPosition);
}
-cmStringRange cmStateDirectory::GetCompileDefinitionsEntries() const
+cmBTStringRange cmStateDirectory::GetCompileDefinitionsEntries() const
{
return GetPropertyContent(
this->DirectoryState->CompileDefinitions,
this->Snapshot_.Position->CompileDefinitionsPosition);
}
-cmBacktraceRange cmStateDirectory::GetCompileDefinitionsEntryBacktraces() const
-{
- return GetPropertyBacktraces(
- this->DirectoryState->CompileDefinitions,
- this->DirectoryState->CompileDefinitionsBacktraces,
- this->Snapshot_.Position->CompileDefinitionsPosition);
-}
-
void cmStateDirectory::AppendCompileDefinitionsEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+ const BT<std::string>& vec)
{
AppendEntry(this->DirectoryState->CompileDefinitions,
- this->DirectoryState->CompileDefinitionsBacktraces,
- this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt);
+ this->Snapshot_.Position->CompileDefinitionsPosition, vec);
}
-void cmStateDirectory::SetCompileDefinitions(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::SetCompileDefinitions(const BT<std::string>& vec)
{
SetContent(this->DirectoryState->CompileDefinitions,
- this->DirectoryState->CompileDefinitionsBacktraces,
- this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt);
+ this->Snapshot_.Position->CompileDefinitionsPosition, vec);
}
void cmStateDirectory::ClearCompileDefinitions()
{
ClearContent(this->DirectoryState->CompileDefinitions,
- this->DirectoryState->CompileDefinitionsBacktraces,
this->Snapshot_.Position->CompileDefinitionsPosition);
}
-cmStringRange cmStateDirectory::GetCompileOptionsEntries() const
+cmBTStringRange cmStateDirectory::GetCompileOptionsEntries() const
{
return GetPropertyContent(this->DirectoryState->CompileOptions,
this->Snapshot_.Position->CompileOptionsPosition);
}
-cmBacktraceRange cmStateDirectory::GetCompileOptionsEntryBacktraces() const
-{
- return GetPropertyBacktraces(
- this->DirectoryState->CompileOptions,
- this->DirectoryState->CompileOptionsBacktraces,
- this->Snapshot_.Position->CompileOptionsPosition);
-}
-
-void cmStateDirectory::AppendCompileOptionsEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+void cmStateDirectory::AppendCompileOptionsEntry(const BT<std::string>& vec)
{
AppendEntry(this->DirectoryState->CompileOptions,
- this->DirectoryState->CompileOptionsBacktraces,
- this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt);
+ this->Snapshot_.Position->CompileOptionsPosition, vec);
}
-void cmStateDirectory::SetCompileOptions(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::SetCompileOptions(const BT<std::string>& vec)
{
SetContent(this->DirectoryState->CompileOptions,
- this->DirectoryState->CompileOptionsBacktraces,
- this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt);
+ this->Snapshot_.Position->CompileOptionsPosition, vec);
}
void cmStateDirectory::ClearCompileOptions()
{
ClearContent(this->DirectoryState->CompileOptions,
- this->DirectoryState->CompileOptionsBacktraces,
this->Snapshot_.Position->CompileOptionsPosition);
}
-cmStringRange cmStateDirectory::GetLinkOptionsEntries() const
+cmBTStringRange cmStateDirectory::GetLinkOptionsEntries() const
{
return GetPropertyContent(this->DirectoryState->LinkOptions,
this->Snapshot_.Position->LinkOptionsPosition);
}
-cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const
-{
- return GetPropertyBacktraces(this->DirectoryState->LinkOptions,
- this->DirectoryState->LinkOptionsBacktraces,
- this->Snapshot_.Position->LinkOptionsPosition);
-}
-
-void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::AppendLinkOptionsEntry(const BT<std::string>& vec)
{
AppendEntry(this->DirectoryState->LinkOptions,
- this->DirectoryState->LinkOptionsBacktraces,
- this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+ this->Snapshot_.Position->LinkOptionsPosition, vec);
}
-void cmStateDirectory::SetLinkOptions(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::SetLinkOptions(const BT<std::string>& vec)
{
SetContent(this->DirectoryState->LinkOptions,
- this->DirectoryState->LinkOptionsBacktraces,
- this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt);
+ this->Snapshot_.Position->LinkOptionsPosition, vec);
}
void cmStateDirectory::ClearLinkOptions()
{
ClearContent(this->DirectoryState->LinkOptions,
- this->DirectoryState->LinkOptionsBacktraces,
this->Snapshot_.Position->LinkOptionsPosition);
}
-cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
+cmBTStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
{
return GetPropertyContent(this->DirectoryState->LinkDirectories,
this->Snapshot_.Position->LinkDirectoriesPosition);
}
-cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const
-{
- return GetPropertyBacktraces(
- this->DirectoryState->LinkDirectories,
- this->DirectoryState->LinkDirectoriesBacktraces,
- this->Snapshot_.Position->LinkDirectoriesPosition);
-}
-
-void cmStateDirectory::AppendLinkDirectoriesEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+void cmStateDirectory::AppendLinkDirectoriesEntry(const BT<std::string>& vec)
{
AppendEntry(this->DirectoryState->LinkDirectories,
- this->DirectoryState->LinkDirectoriesBacktraces,
- this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec);
}
-void cmStateDirectory::PrependLinkDirectoriesEntry(
- const std::string& vec, const cmListFileBacktrace& lfbt)
+void cmStateDirectory::PrependLinkDirectoriesEntry(const BT<std::string>& vec)
{
auto entryEnd = this->DirectoryState->LinkDirectories.begin() +
this->Snapshot_.Position->LinkDirectoriesPosition;
@@ -334,42 +251,35 @@ void cmStateDirectory::PrependLinkDirectoriesEntry(
rbegin = std::find(rbegin, rend, cmPropertySentinal);
auto entryIt = rbegin.base();
- auto entryBegin = this->DirectoryState->LinkDirectories.begin();
-
- auto btIt = this->DirectoryState->LinkDirectoriesBacktraces.begin() +
- std::distance(entryBegin, entryIt);
this->DirectoryState->LinkDirectories.insert(entryIt, vec);
- this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt);
this->Snapshot_.Position->LinkDirectoriesPosition =
this->DirectoryState->LinkDirectories.size();
}
-void cmStateDirectory::SetLinkDirectories(const std::string& vec,
- const cmListFileBacktrace& lfbt)
+void cmStateDirectory::SetLinkDirectories(const BT<std::string>& vec)
{
SetContent(this->DirectoryState->LinkDirectories,
- this->DirectoryState->LinkDirectoriesBacktraces,
- this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec);
}
void cmStateDirectory::ClearLinkDirectories()
{
ClearContent(this->DirectoryState->LinkDirectories,
- this->DirectoryState->LinkDirectoriesBacktraces,
this->Snapshot_.Position->LinkDirectoriesPosition);
}
-void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
- cmListFileBacktrace const& lfbt)
+template <typename ValueType>
+void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value,
+ cmListFileBacktrace const& lfbt)
{
if (prop == "INCLUDE_DIRECTORIES") {
if (!value) {
this->ClearIncludeDirectories();
return;
}
- this->SetIncludeDirectories(value, lfbt);
+ this->SetIncludeDirectories(BT<std::string>(value, lfbt));
return;
}
if (prop == "COMPILE_OPTIONS") {
@@ -377,7 +287,7 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->ClearCompileOptions();
return;
}
- this->SetCompileOptions(value, lfbt);
+ this->SetCompileOptions(BT<std::string>(value, lfbt));
return;
}
if (prop == "COMPILE_DEFINITIONS") {
@@ -385,7 +295,7 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->ClearCompileDefinitions();
return;
}
- this->SetCompileDefinitions(value, lfbt);
+ this->SetCompileDefinitions(BT<std::string>(value, lfbt));
return;
}
if (prop == "LINK_OPTIONS") {
@@ -393,7 +303,7 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->ClearLinkOptions();
return;
}
- this->SetLinkOptions(value, lfbt);
+ this->SetLinkOptions(BT<std::string>(value, lfbt));
return;
}
if (prop == "LINK_DIRECTORIES") {
@@ -401,66 +311,78 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->ClearLinkDirectories();
return;
}
- this->SetLinkDirectories(value, lfbt);
+ this->SetLinkDirectories(BT<std::string>(value, lfbt));
return;
}
this->DirectoryState->Properties.SetProperty(prop, value);
}
+void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
+ cmListFileBacktrace const& lfbt)
+{
+ this->StoreProperty(prop, value, lfbt);
+}
+void cmStateDirectory::SetProperty(const std::string& prop, cmValue value,
+ cmListFileBacktrace const& lfbt)
+{
+ this->StoreProperty(prop, value, lfbt);
+}
+
void cmStateDirectory::AppendProperty(const std::string& prop,
const std::string& value, bool asString,
cmListFileBacktrace const& lfbt)
{
if (prop == "INCLUDE_DIRECTORIES") {
- this->AppendIncludeDirectoriesEntry(value, lfbt);
+ this->AppendIncludeDirectoriesEntry(BT<std::string>(value, lfbt));
return;
}
if (prop == "COMPILE_OPTIONS") {
- this->AppendCompileOptionsEntry(value, lfbt);
+ this->AppendCompileOptionsEntry(BT<std::string>(value, lfbt));
return;
}
if (prop == "COMPILE_DEFINITIONS") {
- this->AppendCompileDefinitionsEntry(value, lfbt);
+ this->AppendCompileDefinitionsEntry(BT<std::string>(value, lfbt));
return;
}
if (prop == "LINK_OPTIONS") {
- this->AppendLinkOptionsEntry(value, lfbt);
+ this->AppendLinkOptionsEntry(BT<std::string>(value, lfbt));
return;
}
if (prop == "LINK_DIRECTORIES") {
- this->AppendLinkDirectoriesEntry(value, lfbt);
+ this->AppendLinkDirectoriesEntry(BT<std::string>(value, lfbt));
return;
}
this->DirectoryState->Properties.AppendProperty(prop, value, asString);
}
-cmProp cmStateDirectory::GetProperty(const std::string& prop) const
+cmValue cmStateDirectory::GetProperty(const std::string& prop) const
{
const bool chain =
this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY);
return this->GetProperty(prop, chain);
}
-cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
+cmValue cmStateDirectory::GetProperty(const std::string& prop,
+ bool chain) const
{
static std::string output;
output.clear();
if (prop == "PARENT_DIRECTORY") {
cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
if (parent.IsValid()) {
- return &parent.GetDirectory().GetCurrentSource();
+ return cmValue(parent.GetDirectory().GetCurrentSource());
}
- return &output;
+ return cmValue(output);
}
if (prop == kBINARY_DIR) {
output = this->GetCurrentBinary();
- return &output;
+ return cmValue(output);
}
if (prop == kSOURCE_DIR) {
output = this->GetCurrentSource();
- return &output;
+ return cmValue(output);
}
if (prop == kSUBDIRECTORIES) {
std::vector<std::string> child_dirs;
@@ -471,15 +393,15 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
child_dirs.push_back(ci.GetDirectory().GetCurrentSource());
}
output = cmJoin(child_dirs, ";");
- return &output;
+ return cmValue(output);
}
if (prop == kBUILDSYSTEM_TARGETS) {
output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
- return &output;
+ return cmValue(output);
}
if (prop == "IMPORTED_TARGETS"_s) {
output = cmJoin(this->DirectoryState->ImportedTargetNames, ";");
- return &output;
+ return cmValue(output);
}
if (prop == "LISTFILE_STACK") {
@@ -491,41 +413,41 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
}
std::reverse(listFiles.begin(), listFiles.end());
output = cmJoin(listFiles, ";");
- return &output;
+ return cmValue(output);
}
if (prop == "CACHE_VARIABLES") {
output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";");
- return &output;
+ return cmValue(output);
}
if (prop == "VARIABLES") {
std::vector<std::string> res = this->Snapshot_.ClosureKeys();
cm::append(res, this->Snapshot_.State->GetCacheEntryKeys());
std::sort(res.begin(), res.end());
output = cmJoin(res, ";");
- return &output;
+ return cmValue(output);
}
if (prop == "INCLUDE_DIRECTORIES") {
output = cmJoin(this->GetIncludeDirectoriesEntries(), ";");
- return &output;
+ return cmValue(output);
}
if (prop == "COMPILE_OPTIONS") {
output = cmJoin(this->GetCompileOptionsEntries(), ";");
- return &output;
+ return cmValue(output);
}
if (prop == "COMPILE_DEFINITIONS") {
output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
- return &output;
+ return cmValue(output);
}
if (prop == "LINK_OPTIONS") {
output = cmJoin(this->GetLinkOptionsEntries(), ";");
- return &output;
+ return cmValue(output);
}
if (prop == "LINK_DIRECTORIES") {
output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
- return &output;
+ return cmValue(output);
}
- cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
+ cmValue retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
if (!retVal && chain) {
cmStateSnapshot parentSnapshot =
this->Snapshot_.GetBuildsystemDirectoryParent();
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index b8abccb81..6429f3293 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -11,10 +11,9 @@
#include "cmAlgorithms.h"
#include "cmLinkedTree.h"
#include "cmListFileCache.h"
-#include "cmProperty.h"
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
-#include "cmStringAlgorithms.h"
+#include "cmValue.h"
class cmStateDirectory
{
@@ -28,55 +27,41 @@ public:
std::string const& GetCurrentBinary() const;
void SetCurrentBinary(std::string const& dir);
- cmStringRange GetIncludeDirectoriesEntries() const;
- cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const;
- void AppendIncludeDirectoriesEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void PrependIncludeDirectoriesEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void SetIncludeDirectories(std::string const& vec,
- cmListFileBacktrace const& lfbt);
+ cmBTStringRange GetIncludeDirectoriesEntries() const;
+ void AppendIncludeDirectoriesEntry(BT<std::string> const& vec);
+ void PrependIncludeDirectoriesEntry(BT<std::string> const& vec);
+ void SetIncludeDirectories(BT<std::string> const& vec);
void ClearIncludeDirectories();
- cmStringRange GetCompileDefinitionsEntries() const;
- cmBacktraceRange GetCompileDefinitionsEntryBacktraces() const;
- void AppendCompileDefinitionsEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void SetCompileDefinitions(std::string const& vec,
- cmListFileBacktrace const& lfbt);
+ cmBTStringRange GetCompileDefinitionsEntries() const;
+ void AppendCompileDefinitionsEntry(BT<std::string> const& vec);
+ void SetCompileDefinitions(BT<std::string> const& vec);
void ClearCompileDefinitions();
- cmStringRange GetCompileOptionsEntries() const;
- cmBacktraceRange GetCompileOptionsEntryBacktraces() const;
- void AppendCompileOptionsEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void SetCompileOptions(std::string const& vec,
- cmListFileBacktrace const& lfbt);
+ cmBTStringRange GetCompileOptionsEntries() const;
+ void AppendCompileOptionsEntry(BT<std::string> const& vec);
+ void SetCompileOptions(BT<std::string> const& vec);
void ClearCompileOptions();
- cmStringRange GetLinkOptionsEntries() const;
- cmBacktraceRange GetLinkOptionsEntryBacktraces() const;
- void AppendLinkOptionsEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void PrependLinkDirectoriesEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt);
+ cmBTStringRange GetLinkOptionsEntries() const;
+ void AppendLinkOptionsEntry(BT<std::string> const& vec);
+ void PrependLinkDirectoriesEntry(BT<std::string> const& vec);
+ void SetLinkOptions(BT<std::string> const& vec);
void ClearLinkOptions();
- cmStringRange GetLinkDirectoriesEntries() const;
- cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const;
- void AppendLinkDirectoriesEntry(std::string const& vec,
- cmListFileBacktrace const& lfbt);
- void SetLinkDirectories(std::string const& vec,
- cmListFileBacktrace const& lfbt);
+ cmBTStringRange GetLinkDirectoriesEntries() const;
+ void AppendLinkDirectoriesEntry(BT<std::string> const& vec);
+ void SetLinkDirectories(BT<std::string> const& vecs);
void ClearLinkDirectories();
void SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt);
+ void SetProperty(const std::string& prop, cmValue value,
+ cmListFileBacktrace const& lfbt);
void AppendProperty(const std::string& prop, const std::string& value,
bool asString, cmListFileBacktrace const& lfbt);
- cmProp GetProperty(const std::string& prop) const;
- cmProp GetProperty(const std::string& prop, bool chain) const;
+ cmValue GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop, bool chain) const;
bool GetPropertyAsBool(const std::string& prop) const;
std::vector<std::string> GetPropertyKeys() const;
@@ -84,6 +69,10 @@ public:
void AddImportedTargetName(std::string const& name);
private:
+ template <typename ValueType>
+ void StoreProperty(const std::string& prop, ValueType value,
+ cmListFileBacktrace const& lfbt);
+
cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator
DirectoryState;
cmStateSnapshot Snapshot_;
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index 6f475f2ee..fd46eedfa 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -67,20 +67,15 @@ struct cmStateDetail::BuildsystemDirectoryStateType
std::string Location;
std::string OutputLocation;
- std::vector<std::string> IncludeDirectories;
- std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces;
+ std::vector<BT<std::string>> IncludeDirectories;
- std::vector<std::string> CompileDefinitions;
- std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
+ std::vector<BT<std::string>> CompileDefinitions;
- std::vector<std::string> CompileOptions;
- std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
+ std::vector<BT<std::string>> CompileOptions;
- std::vector<std::string> LinkOptions;
- std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+ std::vector<BT<std::string>> LinkOptions;
- std::vector<std::string> LinkDirectories;
- std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
+ std::vector<BT<std::string>> LinkDirectories;
std::vector<std::string> NormalTargetNames;
std::vector<std::string> ImportedTargetNames;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index fbf47ef68..f73df8f08 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -11,14 +11,18 @@
#include "cmDefinitions.h"
#include "cmListFileCache.h"
-#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStatePrivate.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVersion.h"
+#if defined(__CYGWIN__)
+# include "cmStringAlgorithms.h"
+#endif
+
cmStateSnapshot::cmStateSnapshot(cmState* state)
: State(state)
{
@@ -201,8 +205,7 @@ bool cmStateSnapshot::HasDefinedPolicyCMP0011()
return !this->Position->Policies->IsEmpty();
}
-std::string const* cmStateSnapshot::GetDefinition(
- std::string const& name) const
+cmValue cmStateSnapshot::GetDefinition(std::string const& name) const
{
assert(this->Position->Vars.IsValid());
return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
@@ -260,12 +263,10 @@ bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef)
return true;
}
-template <typename T, typename U, typename V>
+template <typename T, typename U>
void InitializeContentFromParent(T& parentContent, T& thisContent,
- U& parentBacktraces, U& thisBacktraces,
- V& contentEndPosition)
+ U& contentEndPosition)
{
- auto parentBegin = parentContent.begin();
auto parentEnd = parentContent.end();
auto parentRbegin = cm::make_reverse_iterator(parentEnd);
@@ -273,12 +274,7 @@ void InitializeContentFromParent(T& parentContent, T& thisContent,
parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal);
auto parentIt = parentRbegin.base();
- thisContent = std::vector<std::string>(parentIt, parentEnd);
-
- auto btIt = parentBacktraces.begin() + std::distance(parentBegin, parentIt);
- auto btEnd = parentBacktraces.end();
-
- thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd);
+ thisContent = std::vector<BT<std::string>>(parentIt, parentEnd);
contentEndPosition = thisContent.size();
}
@@ -360,43 +356,33 @@ void cmStateSnapshot::InitializeFromParent()
InitializeContentFromParent(
parent->BuildSystemDirectory->IncludeDirectories,
this->Position->BuildSystemDirectory->IncludeDirectories,
- parent->BuildSystemDirectory->IncludeDirectoryBacktraces,
- this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces,
this->Position->IncludeDirectoryPosition);
InitializeContentFromParent(
parent->BuildSystemDirectory->CompileDefinitions,
this->Position->BuildSystemDirectory->CompileDefinitions,
- parent->BuildSystemDirectory->CompileDefinitionsBacktraces,
- this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces,
this->Position->CompileDefinitionsPosition);
InitializeContentFromParent(
parent->BuildSystemDirectory->CompileOptions,
this->Position->BuildSystemDirectory->CompileOptions,
- parent->BuildSystemDirectory->CompileOptionsBacktraces,
- this->Position->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->CompileOptionsPosition);
InitializeContentFromParent(
parent->BuildSystemDirectory->LinkOptions,
this->Position->BuildSystemDirectory->LinkOptions,
- parent->BuildSystemDirectory->LinkOptionsBacktraces,
- this->Position->BuildSystemDirectory->LinkOptionsBacktraces,
this->Position->LinkOptionsPosition);
InitializeContentFromParent(
parent->BuildSystemDirectory->LinkDirectories,
this->Position->BuildSystemDirectory->LinkDirectories,
- parent->BuildSystemDirectory->LinkDirectoriesBacktraces,
- this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces,
this->Position->LinkDirectoriesPosition);
- cmProp include_regex =
+ cmValue include_regex =
parent->BuildSystemDirectory->Properties.GetPropertyValue(
"INCLUDE_REGULAR_EXPRESSION");
this->Position->BuildSystemDirectory->Properties.SetProperty(
- "INCLUDE_REGULAR_EXPRESSION", cmToCStr(include_regex));
+ "INCLUDE_REGULAR_EXPRESSION", include_regex);
}
cmState* cmStateSnapshot::GetState() const
diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h
index d06cba37a..a61ec8337 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -13,6 +13,7 @@
#include "cmLinkedTree.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
class cmState;
class cmStateDirectory;
@@ -23,7 +24,7 @@ public:
cmStateSnapshot(cmState* state = nullptr);
cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
- std::string const* GetDefinition(std::string const& name) const;
+ cmValue GetDefinition(std::string const& name) const;
bool IsInitialized(std::string const& name) const;
void SetDefinition(std::string const& name, cm::string_view value);
void RemoveDefinition(std::string const& name);
diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx
index 5bb6e7bc5..1bb680819 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -218,85 +218,6 @@ std::string cmCatViews(std::initializer_list<cm::string_view> views)
return result;
}
-bool cmIsInternallyOn(cm::string_view val)
-{
- return (val.size() == 4) && //
- (val[0] == 'I' || val[0] == 'i') && //
- (val[1] == '_') && //
- (val[2] == 'O' || val[2] == 'o') && //
- (val[3] == 'N' || val[3] == 'n');
-}
-
-bool cmIsNOTFOUND(cm::string_view val)
-{
- return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND");
-}
-
-bool cmIsOn(cm::string_view val)
-{
- switch (val.size()) {
- case 1:
- return val[0] == '1' || val[0] == 'Y' || val[0] == 'y';
- case 2:
- return //
- (val[0] == 'O' || val[0] == 'o') && //
- (val[1] == 'N' || val[1] == 'n');
- case 3:
- return //
- (val[0] == 'Y' || val[0] == 'y') && //
- (val[1] == 'E' || val[1] == 'e') && //
- (val[2] == 'S' || val[2] == 's');
- case 4:
- return //
- (val[0] == 'T' || val[0] == 't') && //
- (val[1] == 'R' || val[1] == 'r') && //
- (val[2] == 'U' || val[2] == 'u') && //
- (val[3] == 'E' || val[3] == 'e');
- default:
- break;
- }
-
- return false;
-}
-
-bool cmIsOff(cm::string_view val)
-{
- switch (val.size()) {
- case 0:
- return true;
- case 1:
- return val[0] == '0' || val[0] == 'N' || val[0] == 'n';
- case 2:
- return //
- (val[0] == 'N' || val[0] == 'n') && //
- (val[1] == 'O' || val[1] == 'o');
- case 3:
- return //
- (val[0] == 'O' || val[0] == 'o') && //
- (val[1] == 'F' || val[1] == 'f') && //
- (val[2] == 'F' || val[2] == 'f');
- case 5:
- return //
- (val[0] == 'F' || val[0] == 'f') && //
- (val[1] == 'A' || val[1] == 'a') && //
- (val[2] == 'L' || val[2] == 'l') && //
- (val[3] == 'S' || val[3] == 's') && //
- (val[4] == 'E' || val[4] == 'e');
- case 6:
- return //
- (val[0] == 'I' || val[0] == 'i') && //
- (val[1] == 'G' || val[1] == 'g') && //
- (val[2] == 'N' || val[2] == 'n') && //
- (val[3] == 'O' || val[3] == 'o') && //
- (val[4] == 'R' || val[4] == 'r') && //
- (val[5] == 'E' || val[5] == 'e');
- default:
- break;
- }
-
- return cmIsNOTFOUND(val);
-}
-
bool cmStrToLong(const char* str, long* value)
{
errno = 0;
diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h
index 6b458ec52..492e588bb 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -15,24 +15,11 @@
#include <cm/string_view>
#include "cmRange.h"
+#include "cmValue.h"
/** String range type. */
using cmStringRange = cmRange<std::vector<std::string>::const_iterator>;
-/** Check for non-empty string. */
-inline bool cmNonempty(const char* str)
-{
- return str && *str;
-}
-inline bool cmNonempty(cm::string_view str)
-{
- return !str.empty();
-}
-inline bool cmNonempty(std::string const* str)
-{
- return str && !str->empty();
-}
-
/** Returns length of a literal string. */
template <size_t N>
constexpr size_t cmStrLen(const char (&/*str*/)[N])
@@ -107,6 +94,13 @@ std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep);
*/
void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut,
bool emptyArgs = false);
+inline void cmExpandList(cmValue arg, std::vector<std::string>& argsOut,
+ bool emptyArgs = false)
+{
+ if (arg) {
+ cmExpandList(*arg, argsOut, emptyArgs);
+ }
+}
/**
* Expand out any arguments in the string range [@a first, @a last) that have
@@ -128,6 +122,14 @@ void cmExpandLists(InputIt first, InputIt last,
*/
std::vector<std::string> cmExpandedList(cm::string_view arg,
bool emptyArgs = false);
+inline std::vector<std::string> cmExpandedList(cmValue arg,
+ bool emptyArgs = false)
+{
+ if (!arg) {
+ return {};
+ }
+ return cmExpandedList(*arg, emptyArgs);
+}
/**
* Same as cmExpandList but a new vector is created containing the expanded
@@ -175,6 +177,10 @@ public:
cmAlphaNum(unsigned long long int val);
cmAlphaNum(float val);
cmAlphaNum(double val);
+ cmAlphaNum(cmValue value)
+ : View_(*value)
+ {
+ }
cm::string_view View() const { return this->View_; }
@@ -213,53 +219,6 @@ std::string cmWrap(char prefix, Range const& rng, char suffix,
sep);
}
-/**
- * Does a string indicates that CMake/CPack/CTest internally
- * forced this value. This is not the same as On, but this
- * may be considered as "internally switched on".
- */
-bool cmIsInternallyOn(cm::string_view val);
-inline bool cmIsInternallyOn(const char* val)
-{
- if (!val) {
- return false;
- }
- return cmIsInternallyOn(cm::string_view(val));
-}
-
-/** Return true if value is NOTFOUND or ends in -NOTFOUND. */
-bool cmIsNOTFOUND(cm::string_view val);
-
-/**
- * Does a string indicate a true or ON value? This is not the same as ifdef.
- */
-bool cmIsOn(cm::string_view val);
-inline bool cmIsOn(const char* val)
-{
- return val && cmIsOn(cm::string_view(val));
-}
-inline bool cmIsOn(std::string const* val)
-{
- return val && cmIsOn(*val);
-}
-
-/**
- * Does a string indicate a false or off value ? Note that this is
- * not the same as !IsOn(...) because there are a number of
- * ambiguous values such as "/usr/local/bin" a path will result in
- * IsON and IsOff both returning false. Note that the special path
- * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
- */
-bool cmIsOff(cm::string_view val);
-inline bool cmIsOff(const char* val)
-{
- return !val || cmIsOff(cm::string_view(val));
-}
-inline bool cmIsOff(std::string const* val)
-{
- return !val || cmIsOff(*val);
-}
-
/** Returns true if string @a str starts with the character @a prefix. */
inline bool cmHasPrefix(cm::string_view str, char prefix)
{
@@ -273,6 +232,16 @@ inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix)
}
/** Returns true if string @a str starts with string @a prefix. */
+inline bool cmHasPrefix(cm::string_view str, cmValue prefix)
+{
+ if (!prefix) {
+ return false;
+ }
+
+ return str.compare(0, prefix->size(), *prefix) == 0;
+}
+
+/** Returns true if string @a str starts with string @a prefix. */
template <size_t N>
inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N])
{
@@ -293,6 +262,17 @@ inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix)
}
/** Returns true if string @a str ends with string @a suffix. */
+inline bool cmHasSuffix(cm::string_view str, cmValue suffix)
+{
+ if (!suffix) {
+ return false;
+ }
+
+ return str.size() >= suffix->size() &&
+ str.compare(str.size() - suffix->size(), suffix->size(), *suffix) == 0;
+}
+
+/** Returns true if string @a str ends with string @a suffix. */
template <size_t N>
inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N])
{
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 5fa309df3..f44fcf7c6 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -31,7 +31,6 @@
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmStringReplaceHelper.h"
@@ -39,6 +38,7 @@
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cmUuid.h"
+#include "cmValue.h"
namespace {
@@ -572,7 +572,7 @@ bool HandlePrependCommand(std::vector<std::string> const& args,
const std::string& variable = args[1];
std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
- cmProp oldValue = status.GetMakefile().GetDefinition(variable);
+ cmValue oldValue = status.GetMakefile().GetDefinition(variable);
if (oldValue) {
value += *oldValue;
}
@@ -1054,7 +1054,7 @@ Json::Value& ResolvePath(Json::Value& json, Args path)
}
}
return *search;
-};
+}
Json::Value ReadJson(const std::string& jsonstr)
{
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 10d2e50a4..75a5a8d87 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -20,10 +20,12 @@
#include <cm3p/uv.h>
#include "cmDuration.h"
+#include "cmELF.h"
#include "cmMessageMetadata.h"
#include "cmProcessOutput.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
+#include "cmValue.h"
#if !defined(CMAKE_BOOTSTRAP)
# include <cm3p/archive.h>
@@ -46,10 +48,6 @@
# include "cmCryptoHash.h"
#endif
-#if defined(CMake_USE_ELF_PARSER)
-# include "cmELF.h"
-#endif
-
#if defined(CMake_USE_MACH_PARSER)
# include "cmMachO.h"
#endif
@@ -1595,6 +1593,12 @@ bool cmSystemTools::IsPathToFramework(const std::string& path)
cmHasLiteralSuffix(path, ".framework"));
}
+bool cmSystemTools::IsPathToMacOSSharedLibrary(const std::string& path)
+{
+ return (cmSystemTools::FileIsFullPath(path) &&
+ cmHasLiteralSuffix(path, ".dylib"));
+}
+
bool cmSystemTools::CreateTar(const std::string& outFileName,
const std::vector<std::string>& files,
cmTarCompression compressType, bool verbose,
@@ -1632,7 +1636,10 @@ bool cmSystemTools::CreateTar(const std::string& outFileName,
cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format,
compressionLevel);
- a.Open();
+ if (!a.Open()) {
+ cmSystemTools::Error(a.GetError());
+ return false;
+ }
a.SetMTime(mtime);
a.SetVerbose(verbose);
bool tarCreatedSuccessfully = true;
@@ -2446,14 +2453,12 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message,
bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
std::string& soname)
{
-// For ELF shared libraries use a real parser to get the correct
-// soname.
-#if defined(CMake_USE_ELF_PARSER)
+ // For ELF shared libraries use a real parser to get the correct
+ // soname.
cmELF elf(fullPath.c_str());
if (elf) {
return elf.GetSOName(soname);
}
-#endif
// If the file is not a symlink we have no guess for its soname.
if (!cmSystemTools::FileIsSymlink(fullPath)) {
@@ -2491,7 +2496,6 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
return false;
}
-#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER)
std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
cm::string_view const& want)
{
@@ -2523,9 +2527,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have,
// The desired rpath was not found.
return std::string::npos;
}
-#endif
-#if defined(CMake_USE_ELF_PARSER)
namespace {
struct cmSystemToolsRPathInfo
{
@@ -2539,10 +2541,10 @@ using EmptyCallback = std::function<bool(std::string*, const cmELF&)>;
using AdjustCallback = std::function<bool(
cm::optional<std::string>&, const std::string&, const char*, std::string*)>;
-// FIXME: Dispatch if multiple formats are supported.
-bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
- const AdjustCallback& adjustCallback, std::string* emsg,
- bool* changed)
+cm::optional<bool> AdjustRPathELF(std::string const& file,
+ const EmptyCallback& emptyCallback,
+ const AdjustCallback& adjustCallback,
+ std::string* emsg, bool* changed)
{
if (changed) {
*changed = false;
@@ -2553,6 +2555,9 @@ bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback,
{
// Parse the ELF binary.
cmELF elf(file.c_str());
+ if (!elf) {
+ return cm::nullopt; // Not a valid ELF file.
+ }
// Get the RPATH and RUNPATH entries from it.
int se_count = 0;
@@ -2686,14 +2691,14 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback(
}
return false;
};
-};
+}
}
-bool cmSystemTools::ChangeRPath(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath, std::string* emsg,
- bool* changed)
+cm::optional<bool> ChangeRPathELF(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath,
+ std::string* emsg, bool* changed)
{
auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath](
cm::optional<std::string>& outRPath,
@@ -2741,13 +2746,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
return true;
};
- return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
- changed);
+ return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback,
+ emsg, changed);
}
-bool cmSystemTools::SetRPath(std::string const& file,
- std::string const& newRPath, std::string* emsg,
- bool* changed)
+static cm::optional<bool> SetRPathELF(std::string const& file,
+ std::string const& newRPath,
+ std::string* emsg, bool* changed)
{
auto adjustCallback = [newRPath](cm::optional<std::string>& outRPath,
const std::string& inRPath,
@@ -2759,22 +2764,31 @@ bool cmSystemTools::SetRPath(std::string const& file,
return true;
};
- return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg,
- changed);
+ return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback,
+ emsg, changed);
}
-#elif defined(CMake_USE_XCOFF_PARSER)
-bool cmSystemTools::ChangeRPath(std::string const& file,
- std::string const& oldRPath,
- std::string const& newRPath,
- bool removeEnvironmentRPath, std::string* emsg,
- bool* changed)
+static cm::optional<bool> ChangeRPathXCOFF(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath,
+ std::string* emsg, bool* changed)
{
if (changed) {
*changed = false;
}
-
+#if !defined(CMake_USE_XCOFF_PARSER)
+ (void)file;
+ (void)oldRPath;
+ (void)newRPath;
+ (void)removeEnvironmentRPath;
+ (void)emsg;
+ return cm::nullopt;
+#else
bool chg = false;
cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ if (!xcoff) {
+ return cm::nullopt; // Not a valid XCOFF file
+ }
if (cm::optional<cm::string_view> maybeLibPath = xcoff.GetLibPath()) {
cm::string_view libPath = *maybeLibPath;
// Make sure the current rpath contains the old rpath.
@@ -2830,34 +2844,51 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
*changed = chg;
}
return true;
+#endif
}
-bool cmSystemTools::SetRPath(std::string const& /*file*/,
- std::string const& /*newRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+static cm::optional<bool> SetRPathXCOFF(std::string const& /*file*/,
+ std::string const& /*newRPath*/,
+ std::string* /*emsg*/,
+ bool* /*changed*/)
{
- return false;
+ return cm::nullopt; // Not implemented.
}
-#else
-bool cmSystemTools::ChangeRPath(std::string const& /*file*/,
- std::string const& /*oldRPath*/,
- std::string const& /*newRPath*/,
- bool /*removeEnvironmentRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+
+bool cmSystemTools::ChangeRPath(std::string const& file,
+ std::string const& oldRPath,
+ std::string const& newRPath,
+ bool removeEnvironmentRPath, std::string* emsg,
+ bool* changed)
{
+ if (cm::optional<bool> result = ChangeRPathELF(
+ file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result = ChangeRPathXCOFF(
+ file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) {
+ return result.value();
+ }
return false;
}
-bool cmSystemTools::SetRPath(std::string const& /*file*/,
- std::string const& /*newRPath*/,
- std::string* /*emsg*/, bool* /*changed*/)
+bool cmSystemTools::SetRPath(std::string const& file,
+ std::string const& newRPath, std::string* emsg,
+ bool* changed)
{
+ if (cm::optional<bool> result = SetRPathELF(file, newRPath, emsg, changed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result =
+ SetRPathXCOFF(file, newRPath, emsg, changed)) {
+ return result.value();
+ }
return false;
}
-#endif
-bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
- const char* lhss, const char* rhss)
+namespace {
+bool VersionCompare(cmSystemTools::CompareOp op, const char* lhss,
+ const char* rhss)
{
const char* endl = lhss;
const char* endr = rhss;
@@ -2890,26 +2921,37 @@ bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
// lhs == rhs, so true if operation is EQUAL
return (op & cmSystemTools::OP_EQUAL) != 0;
}
+}
+
+bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
+ const std::string& lhs,
+ const std::string& rhs)
+{
+ return ::VersionCompare(op, lhs.c_str(), rhs.c_str());
+}
+bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
+ const std::string& lhs, const char rhs[])
+{
+ return ::VersionCompare(op, lhs.c_str(), rhs);
+}
bool cmSystemTools::VersionCompareEqual(std::string const& lhs,
std::string const& rhs)
{
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, lhs.c_str(),
- rhs.c_str());
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, lhs, rhs);
}
bool cmSystemTools::VersionCompareGreater(std::string const& lhs,
std::string const& rhs)
{
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, lhs.c_str(),
- rhs.c_str());
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, lhs, rhs);
}
bool cmSystemTools::VersionCompareGreaterEq(std::string const& lhs,
std::string const& rhs)
{
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
- lhs.c_str(), rhs.c_str());
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL, lhs,
+ rhs);
}
static size_t cm_strverscmp_find_first_difference_or_end(const char* lhs,
@@ -2989,10 +3031,8 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
return cm_strverscmp(lhs.c_str(), rhs.c_str());
}
-// FIXME: Dispatch if multiple formats are supported.
-#if defined(CMake_USE_ELF_PARSER)
-bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
- bool* removed)
+static cm::optional<bool> RemoveRPathELF(std::string const& file,
+ std::string* emsg, bool* removed)
{
if (removed) {
*removed = false;
@@ -3005,6 +3045,9 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
{
// Parse the ELF binary.
cmELF elf(file.c_str());
+ if (!elf) {
+ return cm::nullopt; // Not a valid ELF file.
+ }
// Get the RPATH and RUNPATH entries from it and sort them by index
// in the dynamic section header.
@@ -3054,8 +3097,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
entriesErased++;
continue;
}
- if (cmELF::TagMipsRldMapRel != 0 &&
- it->first == cmELF::TagMipsRldMapRel) {
+ if (it->first == cmELF::TagMipsRldMapRel && elf.IsMIPS()) {
// Background: debuggers need to know the "linker map" which contains
// the addresses each dynamic object is loaded at. Most arches use
// the DT_DEBUG tag which the dynamic linker writes to (directly) and
@@ -3131,15 +3173,22 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
}
return true;
}
-#elif defined(CMake_USE_XCOFF_PARSER)
-bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
- bool* removed)
+
+static cm::optional<bool> RemoveRPathXCOFF(std::string const& file,
+ std::string* emsg, bool* removed)
{
if (removed) {
*removed = false;
}
-
+#if !defined(CMake_USE_XCOFF_PARSER)
+ (void)file;
+ (void)emsg;
+ return cm::nullopt; // Cannot handle XCOFF files.
+#else
cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite);
+ if (!xcoff) {
+ return cm::nullopt; // Not a valid XCOFF file.
+ }
bool rm = xcoff.RemoveLibPath();
if (!xcoff) {
if (emsg) {
@@ -3152,55 +3201,60 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
*removed = rm;
}
return true;
+#endif
}
-#else
-bool cmSystemTools::RemoveRPath(std::string const& /*file*/,
- std::string* /*emsg*/, bool* /*removed*/)
+bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
+ bool* removed)
{
+ if (cm::optional<bool> result = RemoveRPathELF(file, emsg, removed)) {
+ return result.value();
+ }
+ if (cm::optional<bool> result = RemoveRPathXCOFF(file, emsg, removed)) {
+ return result.value();
+ }
return false;
}
-#endif
-// FIXME: Dispatch if multiple formats are supported.
bool cmSystemTools::CheckRPath(std::string const& file,
std::string const& newRPath)
{
-#if defined(CMake_USE_ELF_PARSER)
// Parse the ELF binary.
cmELF elf(file.c_str());
-
- // Get the RPATH or RUNPATH entry from it.
- cmELF::StringEntry const* se = elf.GetRPath();
- if (!se) {
- se = elf.GetRunPath();
- }
-
- // Make sure the current rpath contains the new rpath.
- if (newRPath.empty()) {
+ if (elf) {
+ // Get the RPATH or RUNPATH entry from it.
+ cmELF::StringEntry const* se = elf.GetRPath();
if (!se) {
- return true;
+ se = elf.GetRunPath();
}
- } else {
- if (se &&
- cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) {
- return true;
+
+ // Make sure the current rpath contains the new rpath.
+ if (newRPath.empty()) {
+ if (!se) {
+ return true;
+ }
+ } else {
+ if (se &&
+ cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) {
+ return true;
+ }
}
+ return false;
}
- return false;
-#elif defined(CMake_USE_XCOFF_PARSER)
+#if defined(CMake_USE_XCOFF_PARSER)
// Parse the XCOFF binary.
cmXCOFF xcoff(file.c_str());
- if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) {
- if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) {
- return true;
+ if (xcoff) {
+ if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) {
+ if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) {
+ return true;
+ }
}
+ return false;
}
- return false;
-#else
+#endif
(void)file;
(void)newRPath;
return false;
-#endif
}
bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir)
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 44ccbf7a3..715724c3c 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -102,7 +102,11 @@ public:
}
//! Return true if the path is a framework
- static bool IsPathToFramework(const std::string& value);
+ static bool IsPathToFramework(const std::string& path);
+
+ //! Return true if the path is a macOS non-framework shared library (aka
+ //! .dylib)
+ static bool IsPathToMacOSSharedLibrary(const std::string& path);
static bool DoesFileExistWithExtensions(
const std::string& name, const std::vector<std::string>& sourceExts);
@@ -280,7 +284,10 @@ public:
/**
* Compare versions
*/
- static bool VersionCompare(CompareOp op, const char* lhs, const char* rhs);
+ static bool VersionCompare(CompareOp op, const std::string& lhs,
+ const std::string& rhs);
+ static bool VersionCompare(CompareOp op, const std::string& lhs,
+ const char rhs[]);
static bool VersionCompareEqual(std::string const& lhs,
std::string const& rhs);
static bool VersionCompareGreater(std::string const& lhs,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 762270051..97d60cf03 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -37,6 +37,7 @@
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTargetPropertyComputer.h"
+#include "cmValue.h"
#include "cmake.h"
template <>
@@ -79,19 +80,19 @@ const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>(
}
template <>
-cmProp cmTargetPropertyComputer::GetSources<cmTarget>(
+cmValue cmTargetPropertyComputer::GetSources<cmTarget>(
cmTarget const* tgt, cmMessenger* messenger,
cmListFileBacktrace const& context)
{
- cmStringRange entries = tgt->GetSourceEntries();
+ cmBTStringRange entries = tgt->GetSourceEntries();
if (entries.empty()) {
return nullptr;
}
std::ostringstream ss;
const char* sep = "";
- for (std::string const& entry : entries) {
- std::vector<std::string> files = cmExpandedList(entry);
+ for (auto const& entry : entries) {
+ std::vector<std::string> files = cmExpandedList(entry.Value);
for (std::string const& file : files) {
if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
file.back() == '>') {
@@ -112,12 +113,14 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>(
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
noMessage = false;
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
addContent = true;
+ break;
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
@@ -157,7 +160,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>(
}
static std::string srcs;
srcs = ss.str();
- return &srcs;
+ return cmValue(srcs);
}
class cmTargetInternals
@@ -187,24 +190,16 @@ public:
std::set<std::string> SystemIncludeDirectories;
cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
std::map<std::string, BTs<std::string>> LanguageStandardProperties;
- std::vector<std::string> IncludeDirectoriesEntries;
- std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces;
- std::vector<std::string> CompileOptionsEntries;
- std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
- std::vector<std::string> CompileFeaturesEntries;
- std::vector<cmListFileBacktrace> CompileFeaturesBacktraces;
- std::vector<std::string> CompileDefinitionsEntries;
- std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;
- std::vector<std::string> PrecompileHeadersEntries;
- std::vector<cmListFileBacktrace> PrecompileHeadersBacktraces;
- std::vector<std::string> SourceEntries;
- std::vector<cmListFileBacktrace> SourceBacktraces;
- std::vector<std::string> LinkOptionsEntries;
- std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
- std::vector<std::string> LinkDirectoriesEntries;
- std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
- std::vector<std::string> LinkImplementationPropertyEntries;
- std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
+ std::vector<BT<std::string>> IncludeDirectoriesEntries;
+ std::vector<std::string> InstallIncludeDirectoriesEntries;
+ std::vector<BT<std::string>> CompileOptionsEntries;
+ std::vector<BT<std::string>> CompileFeaturesEntries;
+ std::vector<BT<std::string>> CompileDefinitionsEntries;
+ std::vector<BT<std::string>> PrecompileHeadersEntries;
+ std::vector<BT<std::string>> SourceEntries;
+ std::vector<BT<std::string>> LinkOptionsEntries;
+ std::vector<BT<std::string>> LinkDirectoriesEntries;
+ std::vector<BT<std::string>> LinkImplementationPropertyEntries;
std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
TLLCommands;
cmListFileBacktrace Backtrace;
@@ -265,16 +260,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
auto initProp = [this, mf, &defKey](const std::string& property) {
// Replace everything after "CMAKE_"
defKey.replace(defKey.begin() + 6, defKey.end(), property);
- if (cmProp value = mf->GetDefinition(defKey)) {
- this->SetProperty(property, *value);
+ if (cmValue value = mf->GetDefinition(defKey)) {
+ this->SetProperty(property, value);
}
};
auto initPropValue = [this, mf, &defKey](const std::string& property,
const char* default_value) {
// Replace everything after "CMAKE_"
defKey.replace(defKey.begin() + 6, defKey.end(), property);
- if (cmProp value = mf->GetDefinition(defKey)) {
- this->SetProperty(property, *value);
+ if (cmValue value = mf->GetDefinition(defKey)) {
+ this->SetProperty(property, value);
} else if (default_value) {
this->SetProperty(property, default_value);
}
@@ -481,8 +476,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// of the same directory property:
cm::append(this->impl->IncludeDirectoriesEntries,
this->impl->Makefile->GetIncludeDirectoriesEntries());
- cm::append(this->impl->IncludeDirectoriesBacktraces,
- this->impl->Makefile->GetIncludeDirectoriesBacktraces());
{
auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories();
@@ -492,18 +485,12 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
cm::append(this->impl->CompileOptionsEntries,
this->impl->Makefile->GetCompileOptionsEntries());
- cm::append(this->impl->CompileOptionsBacktraces,
- this->impl->Makefile->GetCompileOptionsBacktraces());
cm::append(this->impl->LinkOptionsEntries,
this->impl->Makefile->GetLinkOptionsEntries());
- cm::append(this->impl->LinkOptionsBacktraces,
- this->impl->Makefile->GetLinkOptionsBacktraces());
cm::append(this->impl->LinkDirectoriesEntries,
this->impl->Makefile->GetLinkDirectoriesEntries());
- cm::append(this->impl->LinkDirectoriesBacktraces,
- this->impl->Makefile->GetLinkDirectoriesBacktraces());
}
if (this->impl->TargetType == cmStateEnums::EXECUTABLE) {
@@ -541,7 +528,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// check for "CMAKE_VS_GLOBALS" variable and set up target properties
// if any
- cmProp globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
+ cmValue globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
if (globals) {
const std::string genName = mf->GetGlobalGenerator()->GetName();
if (cmHasLiteralPrefix(genName, "Visual Studio")) {
@@ -612,11 +599,9 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang,
const std::string& feature)
{
cmListFileBacktrace featureBacktrace;
- for (size_t i = 0; i < this->impl->CompileFeaturesEntries.size(); i++) {
- if (this->impl->CompileFeaturesEntries[i] == feature) {
- if (i < this->impl->CompileFeaturesBacktraces.size()) {
- featureBacktrace = this->impl->CompileFeaturesBacktraces[i];
- }
+ for (auto const& entry : this->impl->CompileFeaturesEntries) {
+ if (entry.Value == feature) {
+ featureBacktrace = entry.Backtrace;
break;
}
}
@@ -728,8 +713,7 @@ void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
if (!srcs.empty()) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->SourceEntries.push_back(cmJoin(srcs, ";"));
- this->impl->SourceBacktraces.push_back(lfbt);
+ this->impl->SourceEntries.emplace_back(cmJoin(srcs, ";"), lfbt);
}
}
@@ -753,8 +737,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
}
if (!srcFiles.empty()) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->SourceEntries.push_back(std::move(srcFiles));
- this->impl->SourceBacktraces.push_back(lfbt);
+ this->impl->SourceEntries.emplace_back(std::move(srcFiles), lfbt);
}
}
@@ -842,9 +825,9 @@ public:
{
}
- bool operator()(std::string const& entry)
+ bool operator()(BT<std::string> const& entry)
{
- std::vector<std::string> files = cmExpandedList(entry);
+ std::vector<std::string> files = cmExpandedList(entry.Value);
std::vector<cmSourceFileLocation> locations;
locations.reserve(files.size());
std::transform(files.begin(), files.end(), std::back_inserter(locations),
@@ -865,11 +848,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->SourceEntries.insert(before ? this->impl->SourceEntries.begin()
: this->impl->SourceEntries.end(),
- src);
- this->impl->SourceBacktraces.insert(
- before ? this->impl->SourceBacktraces.begin()
- : this->impl->SourceBacktraces.end(),
- lfbt);
+ BT<std::string>(src, lfbt));
}
if (cmGeneratorExpression::Find(src) != std::string::npos) {
return nullptr;
@@ -1042,7 +1021,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
std::string targetEntry = cmStrCat(this->impl->Name, "_LIB_DEPENDS");
std::string dependencies;
- cmProp old_val = mf.GetDefinition(targetEntry);
+ cmValue old_val = mf.GetDefinition(targetEntry);
if (old_val) {
dependencies += *old_val;
}
@@ -1075,122 +1054,115 @@ std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
return this->impl->SystemIncludeDirectories;
}
-cmStringRange cmTarget::GetIncludeDirectoriesEntries() const
+void cmTarget::AddInstallIncludeDirectories(cmStringRange const& incs)
{
- return cmMakeRange(this->impl->IncludeDirectoriesEntries);
+ std::copy(incs.begin(), incs.end(),
+ std::back_inserter(this->impl->InstallIncludeDirectoriesEntries));
}
-cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const
+cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries() const
{
- return cmMakeRange(this->impl->IncludeDirectoriesBacktraces);
+ return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries);
}
-cmStringRange cmTarget::GetCompileOptionsEntries() const
+cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
- return cmMakeRange(this->impl->CompileOptionsEntries);
+ return cmMakeRange(this->impl->IncludeDirectoriesEntries);
}
-cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const
+cmBTStringRange cmTarget::GetCompileOptionsEntries() const
{
- return cmMakeRange(this->impl->CompileOptionsBacktraces);
+ return cmMakeRange(this->impl->CompileOptionsEntries);
}
-cmStringRange cmTarget::GetCompileFeaturesEntries() const
+cmBTStringRange cmTarget::GetCompileFeaturesEntries() const
{
return cmMakeRange(this->impl->CompileFeaturesEntries);
}
-cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const
-{
- return cmMakeRange(this->impl->CompileFeaturesBacktraces);
-}
-
-cmStringRange cmTarget::GetCompileDefinitionsEntries() const
+cmBTStringRange cmTarget::GetCompileDefinitionsEntries() const
{
return cmMakeRange(this->impl->CompileDefinitionsEntries);
}
-cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const
-{
- return cmMakeRange(this->impl->CompileDefinitionsBacktraces);
-}
-
-cmStringRange cmTarget::GetPrecompileHeadersEntries() const
+cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const
{
return cmMakeRange(this->impl->PrecompileHeadersEntries);
}
-cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const
-{
- return cmMakeRange(this->impl->PrecompileHeadersBacktraces);
-}
-
-cmStringRange cmTarget::GetSourceEntries() const
+cmBTStringRange cmTarget::GetSourceEntries() const
{
return cmMakeRange(this->impl->SourceEntries);
}
-cmBacktraceRange cmTarget::GetSourceBacktraces() const
-{
- return cmMakeRange(this->impl->SourceBacktraces);
-}
-
-cmStringRange cmTarget::GetLinkOptionsEntries() const
+cmBTStringRange cmTarget::GetLinkOptionsEntries() const
{
return cmMakeRange(this->impl->LinkOptionsEntries);
}
-cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
+cmBTStringRange cmTarget::GetLinkDirectoriesEntries() const
{
- return cmMakeRange(this->impl->LinkOptionsBacktraces);
+ return cmMakeRange(this->impl->LinkDirectoriesEntries);
}
-cmStringRange cmTarget::GetLinkDirectoriesEntries() const
+cmBTStringRange cmTarget::GetLinkImplementationEntries() const
{
- return cmMakeRange(this->impl->LinkDirectoriesEntries);
+ return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
}
-cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
-{
- return cmMakeRange(this->impl->LinkDirectoriesBacktraces);
+namespace {
+#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
+MAKE_PROP(C_STANDARD);
+MAKE_PROP(CXX_STANDARD);
+MAKE_PROP(CUDA_STANDARD);
+MAKE_PROP(HIP_STANDARD);
+MAKE_PROP(OBJC_STANDARD);
+MAKE_PROP(OBJCXX_STANDARD);
+MAKE_PROP(COMPILE_DEFINITIONS);
+MAKE_PROP(COMPILE_FEATURES);
+MAKE_PROP(COMPILE_OPTIONS);
+MAKE_PROP(PRECOMPILE_HEADERS);
+MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
+MAKE_PROP(CUDA_PTX_COMPILATION);
+MAKE_PROP(EXPORT_NAME);
+MAKE_PROP(IMPORTED);
+MAKE_PROP(IMPORTED_GLOBAL);
+MAKE_PROP(INCLUDE_DIRECTORIES);
+MAKE_PROP(LINK_OPTIONS);
+MAKE_PROP(LINK_DIRECTORIES);
+MAKE_PROP(LINK_LIBRARIES);
+MAKE_PROP(MANUALLY_ADDED_DEPENDENCIES);
+MAKE_PROP(NAME);
+MAKE_PROP(SOURCES);
+MAKE_PROP(TYPE);
+MAKE_PROP(BINARY_DIR);
+MAKE_PROP(SOURCE_DIR);
+MAKE_PROP(FALSE);
+MAKE_PROP(TRUE);
+#undef MAKE_PROP
}
-cmStringRange cmTarget::GetLinkImplementationEntries() const
+namespace {
+// to workaround bug on GCC/AIX
+// Define a template to force conversion to std::string
+template <typename ValueType>
+std::string ConvertToString(ValueType value);
+
+template <>
+std::string ConvertToString<const char*>(const char* value)
{
- return cmMakeRange(this->impl->LinkImplementationPropertyEntries);
+ return std::string(value);
}
-
-cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
+template <>
+std::string ConvertToString<cmValue>(cmValue value)
{
- return cmMakeRange(this->impl->LinkImplementationPropertyBacktraces);
+ return std::string(*value);
+}
}
-void cmTarget::SetProperty(const std::string& prop, const char* value)
+template <typename ValueType>
+void cmTarget::StoreProperty(const std::string& prop, ValueType value)
{
-#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
- MAKE_STATIC_PROP(C_STANDARD);
- MAKE_STATIC_PROP(CXX_STANDARD);
- MAKE_STATIC_PROP(CUDA_STANDARD);
- MAKE_STATIC_PROP(HIP_STANDARD);
- MAKE_STATIC_PROP(OBJC_STANDARD);
- MAKE_STATIC_PROP(OBJCXX_STANDARD);
- MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
- MAKE_STATIC_PROP(COMPILE_FEATURES);
- MAKE_STATIC_PROP(COMPILE_OPTIONS);
- MAKE_STATIC_PROP(PRECOMPILE_HEADERS);
- MAKE_STATIC_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
- MAKE_STATIC_PROP(CUDA_PTX_COMPILATION);
- MAKE_STATIC_PROP(EXPORT_NAME);
- MAKE_STATIC_PROP(IMPORTED_GLOBAL);
- MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
- MAKE_STATIC_PROP(LINK_OPTIONS);
- MAKE_STATIC_PROP(LINK_DIRECTORIES);
- MAKE_STATIC_PROP(LINK_LIBRARIES);
- MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
- MAKE_STATIC_PROP(NAME);
- MAKE_STATIC_PROP(SOURCES);
- MAKE_STATIC_PROP(TYPE);
-#undef MAKE_STATIC_PROP
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
@@ -1231,75 +1203,57 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
if (prop == propINCLUDE_DIRECTORIES) {
this->impl->IncludeDirectoriesEntries.clear();
- this->impl->IncludeDirectoriesBacktraces.clear();
if (value) {
- this->impl->IncludeDirectoriesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->IncludeDirectoriesBacktraces.push_back(lfbt);
+ this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == propCOMPILE_OPTIONS) {
this->impl->CompileOptionsEntries.clear();
- this->impl->CompileOptionsBacktraces.clear();
if (value) {
- this->impl->CompileOptionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileOptionsBacktraces.push_back(lfbt);
+ this->impl->CompileOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == propCOMPILE_FEATURES) {
this->impl->CompileFeaturesEntries.clear();
- this->impl->CompileFeaturesBacktraces.clear();
if (value) {
- this->impl->CompileFeaturesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileFeaturesBacktraces.push_back(lfbt);
+ this->impl->CompileFeaturesEntries.emplace_back(value, lfbt);
}
} else if (prop == propCOMPILE_DEFINITIONS) {
this->impl->CompileDefinitionsEntries.clear();
- this->impl->CompileDefinitionsBacktraces.clear();
if (value) {
- this->impl->CompileDefinitionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileDefinitionsBacktraces.push_back(lfbt);
+ this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt);
}
} else if (prop == propLINK_OPTIONS) {
this->impl->LinkOptionsEntries.clear();
- this->impl->LinkOptionsBacktraces.clear();
if (value) {
- this->impl->LinkOptionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkOptionsBacktraces.push_back(lfbt);
+ this->impl->LinkOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == propLINK_DIRECTORIES) {
this->impl->LinkDirectoriesEntries.clear();
- this->impl->LinkDirectoriesBacktraces.clear();
if (value) {
- this->impl->LinkDirectoriesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == propPRECOMPILE_HEADERS) {
this->impl->PrecompileHeadersEntries.clear();
- this->impl->PrecompileHeadersBacktraces.clear();
if (value) {
- this->impl->PrecompileHeadersEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->PrecompileHeadersBacktraces.push_back(lfbt);
+ this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
}
} else if (prop == propLINK_LIBRARIES) {
this->impl->LinkImplementationPropertyEntries.clear();
- this->impl->LinkImplementationPropertyBacktraces.clear();
if (value) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkImplementationPropertyEntries.emplace_back(value);
- this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propSOURCES) {
this->impl->SourceEntries.clear();
- this->impl->SourceBacktraces.clear();
if (value) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->SourceEntries.emplace_back(value);
- this->impl->SourceBacktraces.push_back(lfbt);
+ this->impl->SourceEntries.emplace_back(value, lfbt);
}
} else if (prop == propIMPORTED_GLOBAL) {
if (!cmIsOn(value)) {
@@ -1315,7 +1269,8 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->GetGlobalGenerator()->IndexTarget(this);
}
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
- !this->impl->CheckImportedLibName(prop, value ? value : "")) {
+ !this->impl->CheckImportedLibName(
+ prop, value ? value : std::string{})) {
/* error was reported by check method */
} else if (prop == propCUDA_PTX_COMPILATION &&
this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
@@ -1345,17 +1300,17 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
if (reusedFrom.empty()) {
- reusedFrom = value;
+ reusedFrom = ConvertToString(value);
}
- this->impl->Properties.SetProperty(prop, reusedFrom.c_str());
+ this->impl->Properties.SetProperty(prop, reusedFrom);
reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom);
reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
cmStrCat(reusedFrom, ".dir/"));
- cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
- this->SetProperty("COMPILE_PDB_NAME", cmToCStr(tmp));
+ cmValue tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
+ this->SetProperty("COMPILE_PDB_NAME", tmp);
this->AddUtility(reusedFrom, false, this->impl->Makefile);
} else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
@@ -1403,39 +1358,33 @@ void cmTarget::AppendProperty(const std::string& prop,
}
if (prop == "INCLUDE_DIRECTORIES") {
if (!value.empty()) {
- this->impl->IncludeDirectoriesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->IncludeDirectoriesBacktraces.push_back(lfbt);
+ this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_OPTIONS") {
if (!value.empty()) {
- this->impl->CompileOptionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileOptionsBacktraces.push_back(lfbt);
+ this->impl->CompileOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_FEATURES") {
if (!value.empty()) {
- this->impl->CompileFeaturesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileFeaturesBacktraces.push_back(lfbt);
+ this->impl->CompileFeaturesEntries.emplace_back(value, lfbt);
}
} else if (prop == "COMPILE_DEFINITIONS") {
if (!value.empty()) {
- this->impl->CompileDefinitionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->CompileDefinitionsBacktraces.push_back(lfbt);
+ this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_OPTIONS") {
if (!value.empty()) {
- this->impl->LinkOptionsEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkOptionsBacktraces.push_back(lfbt);
+ this->impl->LinkOptionsEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_DIRECTORIES") {
if (!value.empty()) {
- this->impl->LinkDirectoriesEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkDirectoriesBacktraces.push_back(lfbt);
+ this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt);
}
} else if (prop == "PRECOMPILE_HEADERS") {
if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
@@ -1447,20 +1396,17 @@ void cmTarget::AppendProperty(const std::string& prop,
return;
}
if (!value.empty()) {
- this->impl->PrecompileHeadersEntries.emplace_back(value);
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->PrecompileHeadersBacktraces.push_back(lfbt);
+ this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt);
}
} else if (prop == "LINK_LIBRARIES") {
if (!value.empty()) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->LinkImplementationPropertyEntries.emplace_back(value);
- this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt);
+ this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == "SOURCES") {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
- this->impl->SourceEntries.emplace_back(value);
- this->impl->SourceBacktraces.push_back(lfbt);
+ this->impl->SourceEntries.emplace_back(value, lfbt);
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be APPENDed.");
@@ -1474,6 +1420,15 @@ void cmTarget::AppendProperty(const std::string& prop,
}
}
+void cmTarget::SetProperty(const std::string& prop, const char* value)
+{
+ this->StoreProperty(prop, value);
+}
+void cmTarget::SetProperty(const std::string& prop, cmValue value)
+{
+ this->StoreProperty(prop, value);
+}
+
void cmTarget::AppendBuildInterfaceIncludes()
{
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
@@ -1501,70 +1456,46 @@ void cmTarget::AppendBuildInterfaceIncludes()
}
}
-void cmTarget::InsertInclude(std::string const& entry,
- cmListFileBacktrace const& bt, bool before)
+void cmTarget::InsertInclude(BT<std::string> const& entry, bool before)
{
auto position = before ? this->impl->IncludeDirectoriesEntries.begin()
: this->impl->IncludeDirectoriesEntries.end();
- auto btPosition = before ? this->impl->IncludeDirectoriesBacktraces.begin()
- : this->impl->IncludeDirectoriesBacktraces.end();
-
this->impl->IncludeDirectoriesEntries.insert(position, entry);
- this->impl->IncludeDirectoriesBacktraces.insert(btPosition, bt);
}
-void cmTarget::InsertCompileOption(std::string const& entry,
- cmListFileBacktrace const& bt, bool before)
+void cmTarget::InsertCompileOption(BT<std::string> const& entry, bool before)
{
auto position = before ? this->impl->CompileOptionsEntries.begin()
: this->impl->CompileOptionsEntries.end();
- auto btPosition = before ? this->impl->CompileOptionsBacktraces.begin()
- : this->impl->CompileOptionsBacktraces.end();
-
this->impl->CompileOptionsEntries.insert(position, entry);
- this->impl->CompileOptionsBacktraces.insert(btPosition, bt);
}
-void cmTarget::InsertCompileDefinition(std::string const& entry,
- cmListFileBacktrace const& bt)
+void cmTarget::InsertCompileDefinition(BT<std::string> const& entry)
{
this->impl->CompileDefinitionsEntries.push_back(entry);
- this->impl->CompileDefinitionsBacktraces.push_back(bt);
}
-void cmTarget::InsertLinkOption(std::string const& entry,
- cmListFileBacktrace const& bt, bool before)
+void cmTarget::InsertLinkOption(BT<std::string> const& entry, bool before)
{
auto position = before ? this->impl->LinkOptionsEntries.begin()
: this->impl->LinkOptionsEntries.end();
- auto btPosition = before ? this->impl->LinkOptionsBacktraces.begin()
- : this->impl->LinkOptionsBacktraces.end();
-
this->impl->LinkOptionsEntries.insert(position, entry);
- this->impl->LinkOptionsBacktraces.insert(btPosition, bt);
}
-void cmTarget::InsertLinkDirectory(std::string const& entry,
- cmListFileBacktrace const& bt, bool before)
+void cmTarget::InsertLinkDirectory(BT<std::string> const& entry, bool before)
{
auto position = before ? this->impl->LinkDirectoriesEntries.begin()
: this->impl->LinkDirectoriesEntries.end();
- auto btPosition = before ? this->impl->LinkDirectoriesBacktraces.begin()
- : this->impl->LinkDirectoriesBacktraces.end();
-
this->impl->LinkDirectoriesEntries.insert(position, entry);
- this->impl->LinkDirectoriesBacktraces.insert(btPosition, bt);
}
-void cmTarget::InsertPrecompileHeader(std::string const& entry,
- cmListFileBacktrace const& bt)
+void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry)
{
this->impl->PrecompileHeadersEntries.push_back(entry);
- this->impl->PrecompileHeadersBacktraces.push_back(bt);
}
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
@@ -1651,17 +1582,17 @@ void cmTarget::CheckProperty(const std::string& prop,
{
// Certain properties need checking.
if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) {
- if (cmProp value = this->GetProperty(prop)) {
+ if (cmValue value = this->GetProperty(prop)) {
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false);
}
}
if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) {
- if (cmProp value = this->GetProperty(prop)) {
+ if (cmValue value = this->GetProperty(prop)) {
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true);
}
}
if (prop == "INTERFACE_LINK_LIBRARIES") {
- if (cmProp value = this->GetProperty(prop)) {
+ if (cmValue value = this->GetProperty(prop)) {
cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context);
}
}
@@ -1672,40 +1603,15 @@ void cmTarget::CheckProperty(const std::string& prop,
}
}
-cmProp cmTarget::GetComputedProperty(const std::string& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context) const
+cmValue cmTarget::GetComputedProperty(const std::string& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context) const
{
return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
}
-cmProp cmTarget::GetProperty(const std::string& prop) const
-{
-#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
- MAKE_STATIC_PROP(C_STANDARD);
- MAKE_STATIC_PROP(CXX_STANDARD);
- MAKE_STATIC_PROP(CUDA_STANDARD);
- MAKE_STATIC_PROP(OBJC_STANDARD);
- MAKE_STATIC_PROP(OBJCXX_STANDARD);
- MAKE_STATIC_PROP(LINK_LIBRARIES);
- MAKE_STATIC_PROP(TYPE);
- MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
- MAKE_STATIC_PROP(COMPILE_FEATURES);
- MAKE_STATIC_PROP(COMPILE_OPTIONS);
- MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
- MAKE_STATIC_PROP(LINK_OPTIONS);
- MAKE_STATIC_PROP(LINK_DIRECTORIES);
- MAKE_STATIC_PROP(PRECOMPILE_HEADERS);
- MAKE_STATIC_PROP(IMPORTED);
- MAKE_STATIC_PROP(IMPORTED_GLOBAL);
- MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
- MAKE_STATIC_PROP(NAME);
- MAKE_STATIC_PROP(BINARY_DIR);
- MAKE_STATIC_PROP(SOURCE_DIR);
- MAKE_STATIC_PROP(SOURCES);
- MAKE_STATIC_PROP(FALSE);
- MAKE_STATIC_PROP(TRUE);
-#undef MAKE_STATIC_PROP
+cmValue cmTarget::GetProperty(const std::string& prop) const
+{
static std::unordered_set<std::string> const specialProps{
propC_STANDARD,
propCXX_STANDARD,
@@ -1737,7 +1643,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
if (propertyIter == this->impl->LanguageStandardProperties.end()) {
return nullptr;
}
- return &(propertyIter->second.Value);
+ return cmValue(propertyIter->second.Value);
}
if (prop == propLINK_LIBRARIES) {
if (this->impl->LinkImplementationPropertyEntries.empty()) {
@@ -1746,11 +1652,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
- return &output;
+ return cmValue(output);
}
// the type property returns what type the target is
if (prop == propTYPE) {
- return &cmState::GetTargetTypeName(this->GetType());
+ return cmValue(cmState::GetTargetTypeName(this->GetType()));
}
if (prop == propINCLUDE_DIRECTORIES) {
if (this->impl->IncludeDirectoriesEntries.empty()) {
@@ -1759,7 +1665,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->IncludeDirectoriesEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propCOMPILE_FEATURES) {
if (this->impl->CompileFeaturesEntries.empty()) {
@@ -1768,7 +1674,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileFeaturesEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propCOMPILE_OPTIONS) {
if (this->impl->CompileOptionsEntries.empty()) {
@@ -1777,7 +1683,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileOptionsEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
if (this->impl->CompileDefinitionsEntries.empty()) {
@@ -1786,7 +1692,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileDefinitionsEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propLINK_OPTIONS) {
if (this->impl->LinkOptionsEntries.empty()) {
@@ -1795,7 +1701,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkOptionsEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propLINK_DIRECTORIES) {
if (this->impl->LinkDirectoriesEntries.empty()) {
@@ -1805,7 +1711,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkDirectoriesEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
if (this->impl->Utilities.empty()) {
@@ -1822,7 +1728,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return item.Value.first;
});
output = cmJoin(utilities, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propPRECOMPILE_HEADERS) {
if (this->impl->PrecompileHeadersEntries.empty()) {
@@ -1831,30 +1737,31 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
- return &output;
+ return cmValue(output);
}
if (prop == propIMPORTED) {
- return this->IsImported() ? &propTRUE : &propFALSE;
+ return this->IsImported() ? cmValue(propTRUE) : cmValue(propFALSE);
}
if (prop == propIMPORTED_GLOBAL) {
- return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE;
+ return this->IsImportedGloballyVisible() ? cmValue(propTRUE)
+ : cmValue(propFALSE);
}
if (prop == propNAME) {
- return &this->GetName();
+ return cmValue(this->GetName());
}
if (prop == propBINARY_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentBinary();
+ return cmValue(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentBinary());
}
if (prop == propSOURCE_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentSource();
+ return cmValue(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentSource());
}
}
- cmProp retVal = this->impl->Properties.GetPropertyValue(prop);
+ cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
if (!retVal) {
const bool chain = this->impl->Makefile->GetState()->IsPropertyChained(
prop, cmProperty::TARGET);
@@ -1870,7 +1777,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
std::string const& cmTarget::GetSafeProperty(std::string const& prop) const
{
- cmProp ret = this->GetProperty(prop);
+ cmValue ret = this->GetProperty(prop);
if (ret) {
return *ret;
}
@@ -2031,8 +1938,8 @@ std::string cmTarget::ImportedGetFullPath(
std::string result;
- cmProp loc = nullptr;
- cmProp imp = nullptr;
+ cmValue loc = nullptr;
+ cmValue imp = nullptr;
std::string suffix;
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -2043,9 +1950,9 @@ std::string cmTarget::ImportedGetFullPath(
result = *loc;
} else {
std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
- if (cmProp config_location = this->GetProperty(impProp)) {
+ if (cmValue config_location = this->GetProperty(impProp)) {
result = *config_location;
- } else if (cmProp location =
+ } else if (cmValue location =
this->GetProperty("IMPORTED_LOCATION")) {
result = *location;
}
@@ -2058,9 +1965,9 @@ std::string cmTarget::ImportedGetFullPath(
} else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) {
std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
- if (cmProp config_implib = this->GetProperty(impProp)) {
+ if (cmValue config_implib = this->GetProperty(impProp)) {
result = *config_implib;
- } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) {
+ } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
result = *implib;
}
}
@@ -2138,8 +2045,8 @@ bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
return true;
}
-bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc,
- cmProp& imp, std::string& suffix) const
+bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc,
+ cmValue& imp, std::string& suffix) const
{
std::string config_upper;
if (!desired_config.empty()) {
@@ -2161,7 +2068,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc,
std::vector<std::string> mappedConfigs;
{
std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
- if (cmProp mapValue = this->GetProperty(mapProp)) {
+ if (cmValue mapValue = this->GetProperty(mapProp)) {
cmExpandList(*mapValue, mappedConfigs, true);
}
}
@@ -2243,7 +2150,7 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc,
// any available configuration.
if (!loc && !imp) {
std::vector<std::string> availableConfigs;
- if (cmProp iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
+ if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
cmExpandList(*iconfigs, availableConfigs);
}
for (auto aci = availableConfigs.begin();
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 30d9f5d06..3cf69429c 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -14,10 +14,10 @@
#include "cmAlgorithms.h"
#include "cmListFileCache.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTargetLinkLibraryType.h"
+#include "cmValue.h"
class cmCustomCommand;
class cmGlobalGenerator;
@@ -170,20 +170,21 @@ public:
//! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmValue value);
void SetProperty(const std::string& prop, const std::string& value)
{
- this->SetProperty(prop, value.c_str());
+ this->SetProperty(prop, cmValue(value));
}
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
//! Might return a nullptr if the property is not set or invalid
- cmProp GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop) const;
//! Always returns a valid pointer
std::string const& GetSafeProperty(std::string const& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
- cmProp GetComputedProperty(const std::string& prop, cmMessenger* messenger,
- cmListFileBacktrace const& context) const;
+ cmValue GetComputedProperty(const std::string& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context) const;
//! Get all properties
cmPropertyMap const& GetProperties() const;
@@ -198,8 +199,8 @@ public:
bool IsPerConfig() const;
bool CanCompileSources() const;
- bool GetMappedConfig(std::string const& desired_config, cmProp& loc,
- cmProp& imp, std::string& suffix) const;
+ bool GetMappedConfig(std::string const& desired_config, cmValue& loc,
+ cmValue& imp, std::string& suffix) const;
//! Return whether this target is an executable with symbol exports enabled.
bool IsExecutableWithExports() const;
@@ -216,18 +217,12 @@ public:
//! Get a backtrace from the creation of the target.
cmListFileBacktrace const& GetBacktrace() const;
- void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt,
- bool before = false);
- void InsertCompileOption(std::string const& entry,
- cmListFileBacktrace const& bt, bool before = false);
- void InsertCompileDefinition(std::string const& entry,
- cmListFileBacktrace const& bt);
- void InsertLinkOption(std::string const& entry,
- cmListFileBacktrace const& bt, bool before = false);
- void InsertLinkDirectory(std::string const& entry,
- cmListFileBacktrace const& bt, bool before = false);
- void InsertPrecompileHeader(std::string const& entry,
- cmListFileBacktrace const& bt);
+ void InsertInclude(BT<std::string> const& entry, bool before = false);
+ void InsertCompileOption(BT<std::string> const& entry, bool before = false);
+ void InsertCompileDefinition(BT<std::string> const& entry);
+ void InsertLinkOption(BT<std::string> const& entry, bool before = false);
+ void InsertLinkDirectory(BT<std::string> const& entry, bool before = false);
+ void InsertPrecompileHeader(BT<std::string> const& entry);
void AppendBuildInterfaceIncludes();
@@ -237,6 +232,9 @@ public:
void AddSystemIncludeDirectories(std::set<std::string> const& incs);
std::set<std::string> const& GetSystemIncludeDirectories() const;
+ void AddInstallIncludeDirectories(cmStringRange const& incs);
+ cmStringRange GetInstallIncludeDirectoriesEntries() const;
+
BTs<std::string> const* GetLanguageStandardProperty(
const std::string& propertyName) const;
@@ -244,32 +242,23 @@ public:
std::string const& value,
const std::string& feature);
- cmStringRange GetIncludeDirectoriesEntries() const;
- cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
+ cmBTStringRange GetIncludeDirectoriesEntries() const;
- cmStringRange GetCompileOptionsEntries() const;
- cmBacktraceRange GetCompileOptionsBacktraces() const;
+ cmBTStringRange GetCompileOptionsEntries() const;
- cmStringRange GetCompileFeaturesEntries() const;
- cmBacktraceRange GetCompileFeaturesBacktraces() const;
+ cmBTStringRange GetCompileFeaturesEntries() const;
- cmStringRange GetCompileDefinitionsEntries() const;
- cmBacktraceRange GetCompileDefinitionsBacktraces() const;
+ cmBTStringRange GetCompileDefinitionsEntries() const;
- cmStringRange GetPrecompileHeadersEntries() const;
- cmBacktraceRange GetPrecompileHeadersBacktraces() const;
+ cmBTStringRange GetPrecompileHeadersEntries() const;
- cmStringRange GetSourceEntries() const;
- cmBacktraceRange GetSourceBacktraces() const;
+ cmBTStringRange GetSourceEntries() const;
- cmStringRange GetLinkOptionsEntries() const;
- cmBacktraceRange GetLinkOptionsBacktraces() const;
+ cmBTStringRange GetLinkOptionsEntries() const;
- cmStringRange GetLinkDirectoriesEntries() const;
- cmBacktraceRange GetLinkDirectoriesBacktraces() const;
+ cmBTStringRange GetLinkDirectoriesEntries() const;
- cmStringRange GetLinkImplementationEntries() const;
- cmBacktraceRange GetLinkImplementationBacktraces() const;
+ cmBTStringRange GetLinkImplementationEntries() const;
std::string ImportedGetFullPath(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
@@ -280,6 +269,9 @@ public:
};
private:
+ template <typename ValueType>
+ void StoreProperty(const std::string& prop, ValueType value);
+
// Internal representation details.
friend class cmGeneratorTarget;
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index dee2c10a3..8ca3842d3 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -37,7 +37,8 @@ private:
}
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- tgt->InsertCompileOption(this->Join(content), lfbt, prepend);
+ tgt->InsertCompileOption(BT<std::string>(this->Join(content), lfbt),
+ prepend);
return true; // Successfully handled.
}
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 1e38d8492..19fc9319a 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -29,7 +29,6 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
- std::string InterfaceIncludeDirectories;
///@}
bool NamelinkOnly = false;
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 3897499f3..f31501ebd 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -63,7 +63,7 @@ bool TargetIncludeDirectoriesImpl::HandleDirectContent(
bool system)
{
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- tgt->InsertInclude(this->Join(content), lfbt, prepend);
+ tgt->InsertInclude(BT<std::string>(this->Join(content), lfbt), prepend);
if (system) {
std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/";
std::set<std::string> sdirs;
diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx
index 0c68d604c..3ba27a83a 100644
--- a/Source/cmTargetLinkDirectoriesCommand.cxx
+++ b/Source/cmTargetLinkDirectoriesCommand.cxx
@@ -34,7 +34,8 @@ private:
bool prepend, bool /*system*/) override
{
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend);
+ tgt->InsertLinkDirectory(BT<std::string>(this->Join(content), lfbt),
+ prepend);
return true; // Successfully handled.
}
};
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 3423b30dc..e15c9418a 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -14,13 +14,13 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
+#include "cmValue.h"
#include "cmake.h"
namespace {
@@ -143,6 +143,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n";
modal = "should";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
@@ -150,6 +151,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
case cmPolicies::NEW:
modal = "must";
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (modal) {
e << "Utility target \"" << target->GetName() << "\" " << modal
@@ -278,7 +280,7 @@ bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
// with old versions of CMake and new)
llt = GENERAL_LibraryType;
std::string linkType = cmStrCat(args[0], "_LINK_TYPE");
- cmProp linkTypeString = mf.GetDefinition(linkType);
+ cmValue linkTypeString = mf.GetDefinition(linkType);
if (linkTypeString) {
if (*linkTypeString == "debug") {
llt = DEBUG_LibraryType;
@@ -395,6 +397,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState,
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n";
modal = "should";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
@@ -402,6 +405,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState,
case cmPolicies::NEW:
modal = "must";
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (modal) {
diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx
index df9416fad..3ea2d7175 100644
--- a/Source/cmTargetLinkOptionsCommand.cxx
+++ b/Source/cmTargetLinkOptionsCommand.cxx
@@ -30,7 +30,7 @@ private:
bool prepend, bool /*system*/) override
{
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- tgt->InsertLinkOption(this->Join(content), lfbt, prepend);
+ tgt->InsertLinkOption(BT<std::string>(this->Join(content), lfbt), prepend);
return true; // Successfully handled.
}
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index e41714aba..3bd1ea3c6 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -5,9 +5,9 @@
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmTarget.h"
+#include "cmValue.h"
#include "cmake.h"
cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
@@ -181,7 +181,7 @@ void cmTargetPropCommandBase::HandleInterfaceContent(
{
if (prepend) {
const std::string propName = std::string("INTERFACE_") + this->Property;
- cmProp propValue = tgt->GetProperty(propName);
+ cmValue propValue = tgt->GetProperty(propName);
const std::string totalContent =
this->Join(content) + (propValue ? (";" + *propValue) : std::string());
tgt->SetProperty(propName, totalContent);
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index b9c93659f..9b9414277 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -21,6 +21,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
modal = "should";
+ CM_FALLTHROUGH;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
@@ -28,6 +29,7 @@ bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
case cmPolicies::NEW:
modal = "may";
messageType = MessageType::FATAL_ERROR;
+ break;
}
if (modal) {
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index f2be318b8..e61a1fcda 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -7,10 +7,10 @@
#include <string>
#include "cmListFileCache.h"
-#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
class cmMessenger;
@@ -18,11 +18,11 @@ class cmTargetPropertyComputer
{
public:
template <typename Target>
- static cmProp GetProperty(Target const* tgt, const std::string& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context)
+ static cmValue GetProperty(Target const* tgt, const std::string& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
{
- if (cmProp loc = GetLocation(tgt, prop, messenger, context)) {
+ if (cmValue loc = GetLocation(tgt, prop, messenger, context)) {
return loc;
}
if (cmSystemTools::GetFatalErrorOccured()) {
@@ -46,9 +46,9 @@ private:
std::string const& config);
template <typename Target>
- static cmProp GetLocation(Target const* tgt, std::string const& prop,
- cmMessenger* messenger,
- cmListFileBacktrace const& context)
+ static cmValue GetLocation(Target const* tgt, std::string const& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
{
// Watch for special "computed" properties that are dependent on
@@ -65,7 +65,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocationForBuild(tgt);
+ return cmValue(ComputeLocationForBuild(tgt));
}
// Support "LOCATION_<CONFIG>".
@@ -76,7 +76,7 @@ private:
return nullptr;
}
std::string configName = prop.substr(9);
- return &ComputeLocation(tgt, configName);
+ return cmValue(ComputeLocation(tgt, configName));
}
// Support "<CONFIG>_LOCATION".
@@ -89,7 +89,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocation(tgt, configName);
+ return cmValue(ComputeLocation(tgt, configName));
}
}
}
@@ -97,6 +97,6 @@ private:
}
template <typename Target>
- static cmProp GetSources(Target const* tgt, cmMessenger* messenger,
- cmListFileBacktrace const& context);
+ static cmValue GetSources(Target const* tgt, cmMessenger* messenger,
+ cmListFileBacktrace const& context);
};
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index a26bef3db..7c0f9e722 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -5,7 +5,7 @@
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmState.h"
-#include "cmStringAlgorithms.h"
+#include "cmValue.h"
cmTest::cmTest(cmMakefile* mf)
: CommandExpandLists(false)
@@ -32,20 +32,20 @@ void cmTest::SetCommand(std::vector<std::string> const& command)
this->Command = command;
}
-const char* cmTest::GetProperty(const std::string& prop) const
+cmValue cmTest::GetProperty(const std::string& prop) const
{
- cmProp retVal = this->Properties.GetPropertyValue(prop);
+ cmValue retVal = this->Properties.GetPropertyValue(prop);
if (!retVal) {
const bool chain =
this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST);
if (chain) {
- if (cmProp p = this->Makefile->GetProperty(prop, chain)) {
- return p->c_str();
+ if (cmValue p = this->Makefile->GetProperty(prop, chain)) {
+ return p;
}
}
return nullptr;
}
- return retVal->c_str();
+ return retVal;
}
bool cmTest::GetPropertyAsBool(const std::string& prop) const
@@ -57,6 +57,10 @@ void cmTest::SetProperty(const std::string& prop, const char* value)
{
this->Properties.SetProperty(prop, value);
}
+void cmTest::SetProperty(const std::string& prop, cmValue value)
+{
+ this->Properties.SetProperty(prop, value);
+}
void cmTest::AppendProperty(const std::string& prop, const std::string& value,
bool asString)
diff --git a/Source/cmTest.h b/Source/cmTest.h
index f33b7e286..85978dac2 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -9,6 +9,7 @@
#include "cmListFileCache.h"
#include "cmPropertyMap.h"
+#include "cmValue.h"
class cmMakefile;
@@ -34,9 +35,14 @@ public:
//! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmValue(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
- const char* GetProperty(const std::string& prop) const;
+ cmValue GetProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
cmPropertyMap& GetProperties() { return this->Properties; }
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 7022c4eb1..dbb087608 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -19,13 +19,13 @@
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTest.h"
+#include "cmValue.h"
namespace /* anonymous */
{
@@ -167,7 +167,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
exe = target->GetFullPath(config);
// Prepend with the emulator when cross compiling if required.
- cmProp emulator = target->GetProperty("CROSSCOMPILING_EMULATOR");
+ cmValue emulator = target->GetProperty("CROSSCOMPILING_EMULATOR");
if (cmNonempty(emulator)) {
std::vector<std::string> emulatorWithArgs = cmExpandedList(*emulator);
std::string emulatorExe(emulatorWithArgs[0]);
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 056696d4b..c8f5a4b22 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -18,6 +18,10 @@
#include <cstring>
#include <sstream>
+#ifdef __MINGW32__
+# include <libloaderapi.h>
+#endif
+
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -159,6 +163,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
case 'M':
case 'S':
case 'U':
+ case 'V':
case 'w':
case 'y':
case 'Y':
@@ -189,6 +194,30 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
char buffer[16];
+#ifdef __MINGW32__
+ /* See a bug in MinGW: https://sourceforge.net/p/mingw-w64/bugs/793/. A work
+ * around is to try to use strftime() from ucrtbase.dll. */
+ using T = size_t(WINAPI*)(char*, size_t, const char*, const struct tm*);
+ auto loadUcrtStrftime = []() -> T {
+ auto handle =
+ LoadLibraryExA("ucrtbase.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (handle) {
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wcast-function-type"
+ return reinterpret_cast<T>(GetProcAddress(handle, "strftime"));
+# pragma GCC diagnostic pop
+ }
+ return nullptr;
+ };
+ static T ucrtStrftime = loadUcrtStrftime();
+
+ if (ucrtStrftime) {
+ size_t size =
+ ucrtStrftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct);
+ return std::string(buffer, size);
+ }
+#endif
+
size_t size =
strftime(buffer, sizeof(buffer), formatString.c_str(), &timeStruct);
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 8cac74d34..cc9e15864 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -9,12 +9,12 @@
#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
class cmExecutionStatus;
@@ -162,7 +162,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
if (!this->OutputVariable.empty()) {
// if the TryCompileCore saved output in this outputVariable then
// prepend that output to this output
- cmProp compileOutput =
+ cmValue compileOutput =
this->Makefile->GetDefinition(this->OutputVariable);
if (compileOutput) {
runOutputContents = *compileOutput + runOutputContents;
@@ -260,7 +260,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
comment.c_str(), cmStateEnums::STRING);
cmState* state = this->Makefile->GetState();
- cmProp existingValue = state->GetCacheEntryValue(this->RunResultVariable);
+ cmValue existingValue = state->GetCacheEntryValue(this->RunResultVariable);
if (existingValue) {
state->SetCacheEntryProperty(this->RunResultVariable, "ADVANCED", "1");
}
@@ -282,7 +282,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(),
cmStateEnums::STRING);
cmState* state = this->Makefile->GetState();
- cmProp existing = state->GetCacheEntryValue(internalRunOutputName);
+ cmValue existing = state->GetCacheEntryValue(internalRunOutputName);
if (existing) {
state->SetCacheEntryProperty(internalRunOutputName, "ADVANCED", "1");
}
diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h
index 8c5ad5983..027d6905f 100644
--- a/Source/cmUVHandlePtr.h
+++ b/Source/cmUVHandlePtr.h
@@ -23,7 +23,7 @@
#else
-# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base;
+# define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base
#endif
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index d276c8a60..2805a33bb 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -6,11 +6,11 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmUtilitySourceCommand
bool cmUtilitySourceCommand(std::vector<std::string> const& args,
@@ -25,7 +25,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args,
// The first argument is the cache entry name.
std::string const& cacheEntry = *arg++;
- cmProp cacheValue = status.GetMakefile().GetDefinition(cacheEntry);
+ cmValue cacheValue = status.GetMakefile().GetDefinition(cacheEntry);
// If it exists already and appears up to date then we are done. If
// the string contains "(IntDir)" but that is not the
// CMAKE_CFG_INTDIR setting then the value is out of date.
@@ -85,7 +85,7 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args,
std::string utilityDirectory =
status.GetMakefile().GetCurrentBinaryDirectory();
std::string exePath;
- if (cmProp d =
+ if (cmValue d =
status.GetMakefile().GetDefinition("EXECUTABLE_OUTPUT_PATH")) {
exePath = *d;
}
diff --git a/Source/cmValue.cxx b/Source/cmValue.cxx
new file mode 100644
index 000000000..044db2909
--- /dev/null
+++ b/Source/cmValue.cxx
@@ -0,0 +1,123 @@
+
+#include "cmValue.h"
+
+#include <string>
+
+#include <cmext/string_view>
+
+#include "cmStringAlgorithms.h"
+
+std::string cmValue::Empty;
+
+bool cmValue::IsOn(cm::string_view value) noexcept
+{
+ switch (value.size()) {
+ case 1:
+ return value[0] == '1' || value[0] == 'Y' || value[0] == 'y';
+ case 2:
+ return //
+ (value[0] == 'O' || value[0] == 'o') && //
+ (value[1] == 'N' || value[1] == 'n');
+ case 3:
+ return //
+ (value[0] == 'Y' || value[0] == 'y') && //
+ (value[1] == 'E' || value[1] == 'e') && //
+ (value[2] == 'S' || value[2] == 's');
+ case 4:
+ return //
+ (value[0] == 'T' || value[0] == 't') && //
+ (value[1] == 'R' || value[1] == 'r') && //
+ (value[2] == 'U' || value[2] == 'u') && //
+ (value[3] == 'E' || value[3] == 'e');
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool cmValue::IsOff(cm::string_view value) noexcept
+{
+ switch (value.size()) {
+ case 0:
+ return true;
+ case 1:
+ return value[0] == '0' || value[0] == 'N' || value[0] == 'n';
+ case 2:
+ return //
+ (value[0] == 'N' || value[0] == 'n') && //
+ (value[1] == 'O' || value[1] == 'o');
+ case 3:
+ return //
+ (value[0] == 'O' || value[0] == 'o') && //
+ (value[1] == 'F' || value[1] == 'f') && //
+ (value[2] == 'F' || value[2] == 'f');
+ case 5:
+ return //
+ (value[0] == 'F' || value[0] == 'f') && //
+ (value[1] == 'A' || value[1] == 'a') && //
+ (value[2] == 'L' || value[2] == 'l') && //
+ (value[3] == 'S' || value[3] == 's') && //
+ (value[4] == 'E' || value[4] == 'e');
+ case 6:
+ return //
+ (value[0] == 'I' || value[0] == 'i') && //
+ (value[1] == 'G' || value[1] == 'g') && //
+ (value[2] == 'N' || value[2] == 'n') && //
+ (value[3] == 'O' || value[3] == 'o') && //
+ (value[4] == 'R' || value[4] == 'r') && //
+ (value[5] == 'E' || value[5] == 'e');
+ default:
+ break;
+ }
+
+ return IsNOTFOUND(value);
+}
+
+bool cmValue::IsNOTFOUND(cm::string_view value) noexcept
+{
+ return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s);
+}
+
+bool cmValue::IsInternallyOn(cm::string_view value) noexcept
+{
+ return (value.size() == 4) && //
+ (value[0] == 'I' || value[0] == 'i') && //
+ (value[1] == '_') && //
+ (value[2] == 'O' || value[2] == 'o') && //
+ (value[3] == 'N' || value[3] == 'n');
+}
+
+int cmValue::Compare(cmValue value) const noexcept
+{
+ if (this->Value == nullptr && !value) {
+ return 0;
+ }
+ if (this->Value == nullptr) {
+ return -1;
+ }
+ if (!value) {
+ return 1;
+ }
+ return this->Value->compare(*value);
+}
+
+int cmValue::Compare(cm::string_view value) const noexcept
+{
+ if (this->Value == nullptr && value.data() == nullptr) {
+ return 0;
+ }
+ if (this->Value == nullptr) {
+ return -1;
+ }
+ if (value.data() == nullptr) {
+ return 1;
+ }
+ return cm::string_view(*this->Value).compare(value);
+}
+
+std::ostream& operator<<(std::ostream& o, cmValue v)
+{
+ o << *v;
+ return o;
+}
diff --git a/Source/cmValue.h b/Source/cmValue.h
new file mode 100644
index 000000000..f96d2f5de
--- /dev/null
+++ b/Source/cmValue.h
@@ -0,0 +1,314 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <iosfwd>
+#include <string>
+
+#include <cm/string_view>
+
+class cmValue
+{
+public:
+ cmValue() noexcept = default;
+ cmValue(std::nullptr_t) noexcept {}
+ explicit cmValue(const std::string* value) noexcept
+ : Value(value)
+ {
+ }
+ explicit cmValue(const std::string& value) noexcept
+ : Value(&value)
+ {
+ }
+ cmValue(const cmValue& other) noexcept = default;
+
+ cmValue& operator=(const cmValue& other) noexcept = default;
+ cmValue& operator=(std::nullptr_t) noexcept
+ {
+ this->Value = nullptr;
+ return *this;
+ }
+
+ const std::string* Get() const noexcept { return this->Value; }
+ const char* GetCStr() const noexcept
+ {
+ return this->Value == nullptr ? nullptr : this->Value->c_str();
+ }
+
+ const std::string* operator->() const noexcept
+ {
+ return this->Value == nullptr ? &cmValue::Empty : this->Value;
+ }
+ const std::string& operator*() const noexcept
+ {
+ return this->Value == nullptr ? cmValue::Empty : *this->Value;
+ }
+
+ explicit operator bool() const noexcept { return this->Value != nullptr; }
+ operator const std::string&() const noexcept { return this->operator*(); }
+ explicit operator cm::string_view() const noexcept
+ {
+ return this->operator*();
+ }
+
+ /**
+ * Does the value indicate a true or ON value?
+ */
+ bool IsOn() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmValue::IsOn(cm::string_view(*this->Value));
+ }
+ /**
+ * Does the value indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsOn and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+ bool IsOff() const noexcept
+ {
+ return this->Value == nullptr ||
+ cmValue::IsOff(cm::string_view(*this->Value));
+ }
+ /** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+ bool IsNOTFOUND() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmValue::IsNOTFOUND(cm::string_view(*this->Value));
+ }
+ bool IsEmpty() const noexcept
+ {
+ return this->Value == nullptr || this->Value->empty();
+ }
+
+ /**
+ * Does a string indicates that CMake/CPack/CTest internally
+ * forced this value. This is not the same as On, but this
+ * may be considered as "internally switched on".
+ */
+ bool IsInternallyOn() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmValue::IsInternallyOn(cm::string_view(*this->Value));
+ }
+
+ bool IsSet() const noexcept
+ {
+ return !this->IsEmpty() && !this->IsNOTFOUND();
+ }
+
+ /**
+ * Does a string indicate a true or ON value?
+ */
+ static bool IsOn(const char* value) noexcept
+ {
+ return value != nullptr && IsOn(cm::string_view(value));
+ }
+ static bool IsOn(cm::string_view) noexcept;
+
+ /**
+ * Compare method has same semantic as std::optional::compare
+ */
+ int Compare(cmValue value) const noexcept;
+ int Compare(cm::string_view value) const noexcept;
+
+ /**
+ * Does a string indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsOn and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+ static bool IsOff(const char* value) noexcept
+ {
+ return value == nullptr || IsOff(cm::string_view(value));
+ }
+ static bool IsOff(cm::string_view) noexcept;
+
+ /** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+ static bool IsNOTFOUND(const char* value) noexcept
+ {
+ return value == nullptr || IsNOTFOUND(cm::string_view(value));
+ }
+ static bool IsNOTFOUND(cm::string_view) noexcept;
+
+ static bool IsEmpty(const char* value) noexcept
+ {
+ return value == nullptr || *value == '\0';
+ }
+ static bool IsEmpty(cm::string_view value) noexcept { return value.empty(); }
+
+ /**
+ * Does a string indicates that CMake/CPack/CTest internally
+ * forced this value. This is not the same as On, but this
+ * may be considered as "internally switched on".
+ */
+ static bool IsInternallyOn(const char* value) noexcept
+ {
+ return value != nullptr && IsInternallyOn(cm::string_view(value));
+ }
+ static bool IsInternallyOn(cm::string_view) noexcept;
+
+private:
+ static std::string Empty;
+ const std::string* Value = nullptr;
+};
+
+std::ostream& operator<<(std::ostream& o, cmValue v);
+
+inline bool operator==(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmValue l, cmValue r) noexcept
+{
+ return l.Compare(r) >= 0;
+}
+
+inline bool operator==(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmValue l, cm::string_view r) noexcept
+{
+ return l.Compare(r) >= 0;
+}
+
+inline bool operator==(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) == 0;
+}
+inline bool operator!=(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) != 0;
+}
+inline bool operator<(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) < 0;
+}
+inline bool operator<=(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) <= 0;
+}
+inline bool operator>(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) > 0;
+}
+inline bool operator>=(cmValue l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmValue{}) >= 0;
+}
+
+/**
+ * Does a string indicate a true or ON value? This is not the same as ifdef.
+ */
+inline bool cmIsOn(cm::string_view val)
+{
+ return cmValue::IsOn(val);
+}
+inline bool cmIsOn(const char* val)
+{
+ return cmValue::IsOn(val);
+}
+inline bool cmIsOn(cmValue val)
+{
+ return val.IsOn();
+}
+
+/**
+ * Does a string indicate a false or off value ? Note that this is
+ * not the same as !IsOn(...) because there are a number of
+ * ambiguous values such as "/usr/local/bin" a path will result in
+ * IsON and IsOff both returning false. Note that the special path
+ * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true.
+ */
+inline bool cmIsOff(cm::string_view val)
+{
+ return cmValue::IsOff(val);
+}
+inline bool cmIsOff(const char* val)
+{
+ return cmValue::IsOff(val);
+}
+inline bool cmIsOff(cmValue val)
+{
+ return val.IsOff();
+}
+
+/** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+inline bool cmIsNOTFOUND(cm::string_view val)
+{
+ return cmValue::IsNOTFOUND(val);
+}
+inline bool cmIsNOTFOUND(cmValue val)
+{
+ return val.IsNOTFOUND();
+}
+
+/** Check for non-empty Property/Variable value. */
+inline bool cmNonempty(cm::string_view val)
+{
+ return !cmValue::IsEmpty(val);
+}
+inline bool cmNonempty(const char* val)
+{
+ return !cmValue::IsEmpty(val);
+}
+inline bool cmNonempty(cmValue val)
+{
+ return !val.IsEmpty();
+}
+
+/**
+ * Does a string indicates that CMake/CPack/CTest internally
+ * forced this value. This is not the same as On, but this
+ * may be considered as "internally switched on".
+ */
+inline bool cmIsInternallyOn(cm::string_view val)
+{
+ return cmValue::IsInternallyOn(val);
+}
+inline bool cmIsInternallyOn(const char* val)
+{
+ return cmValue::IsInternallyOn(val);
+}
+inline bool cmIsInternallyOn(cmValue val)
+{
+ return val.IsInternallyOn();
+}
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 1fe03ab26..2b1efbac2 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -4,10 +4,10 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
// cmLibraryCommand
bool cmVariableRequiresCommand(std::vector<std::string> const& args,
@@ -38,7 +38,7 @@ bool cmVariableRequiresCommand(std::vector<std::string> const& args,
}
}
}
- cmProp reqVar = status.GetMakefile().GetDefinition(resultVariable);
+ cmValue reqVar = status.GetMakefile().GetDefinition(resultVariable);
// if reqVar is unset, then set it to requirementsMet
// if reqVar is set to true, but requirementsMet is false , then
// set reqVar to false.
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 7c7fbca5b..fd5402cf6 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -10,9 +10,9 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmVariableWatch.h"
#include "cmake.h"
@@ -45,7 +45,7 @@ void cmVariableWatchCommandVariableAccessed(const std::string& variable,
std::string stack = *mf->GetProperty("LISTFILE_STACK");
if (!data->Command.empty()) {
- cmProp const currentListFile =
+ cmValue const currentListFile =
mf->GetDefinition("CMAKE_CURRENT_LIST_FILE");
const auto fakeLineNo =
std::numeric_limits<decltype(cmListFileArgument::Line)>::max();
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 97cb1bf14..d2c49ae36 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -6,6 +6,7 @@
#include <set>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
@@ -437,7 +438,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->VerifyNecessaryFiles();
}
- cmProp vsProjectTypes =
+ cmValue vsProjectTypes =
this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
if (vsProjectTypes) {
const char* tagName = "ProjectTypes";
@@ -447,11 +448,11 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element(tagName, *vsProjectTypes);
}
- cmProp vsProjectName =
+ cmValue vsProjectName =
this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
- cmProp vsLocalPath =
+ cmValue vsLocalPath =
this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
- cmProp vsProvider =
+ cmValue vsProvider =
this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
if (vsProjectName && vsLocalPath && vsProvider) {
@@ -459,7 +460,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("SccLocalPath", *vsLocalPath);
e1.Element("SccProvider", *vsProvider);
- cmProp vsAuxPath =
+ cmValue vsAuxPath =
this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
if (vsAuxPath) {
e1.Element("SccAuxPath", *vsAuxPath);
@@ -470,7 +471,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("WinMDAssembly", "true");
}
- cmProp vsGlobalKeyword =
+ cmValue vsGlobalKeyword =
this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
if (!vsGlobalKeyword) {
if (this->GlobalGenerator->TargetsAndroid()) {
@@ -482,63 +483,78 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("Keyword", *vsGlobalKeyword);
}
- cmProp vsGlobalRootNamespace =
+ cmValue vsGlobalRootNamespace =
this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
if (vsGlobalRootNamespace) {
e1.Element("RootNamespace", *vsGlobalRootNamespace);
}
e1.Element("Platform", this->Platform);
- cmProp projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = &this->Name;
- }
- e1.Element("ProjectName", *projLabel);
+ cmValue projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
+ e1.Element("ProjectName", projLabel ? projLabel : this->Name);
{
- cmProp targetFramework =
- this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
+ cm::optional<std::string> targetFramework;
+ cm::optional<std::string> targetFrameworkVersion;
+ cm::optional<std::string> targetFrameworkIdentifier;
+ cm::optional<std::string> targetFrameworkTargetsVersion;
+ if (cmValue tf =
+ this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK")) {
+ targetFramework = *tf;
+ } else if (cmValue vstfVer = this->GeneratorTarget->GetProperty(
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
+ // FIXME: Someday, add a deprecation warning for VS_* property.
+ targetFrameworkVersion = *vstfVer;
+ } else if (cmValue tfVer = this->GeneratorTarget->GetProperty(
+ "DOTNET_TARGET_FRAMEWORK_VERSION")) {
+ targetFrameworkVersion = *tfVer;
+ } else if (this->ProjectType == csproj) {
+ targetFrameworkVersion =
+ this->GlobalGenerator->GetTargetFrameworkVersion();
+ }
+ if (this->ProjectType == vcxproj &&
+ this->GlobalGenerator->TargetsWindowsCE()) {
+ e1.Element("EnableRedirectPlatform", "true");
+ e1.Element("RedirectPlatformValue", this->Platform);
+ }
+ if (this->ProjectType == csproj) {
+ if (this->GlobalGenerator->TargetsWindowsCE()) {
+ // FIXME: These target VS_TARGET_FRAMEWORK* target properties
+ // are undocumented settings only ever supported for WinCE.
+ // We need a better way to control these in general.
+ if (cmValue tfId = this->GeneratorTarget->GetProperty(
+ "VS_TARGET_FRAMEWORK_IDENTIFIER")) {
+ targetFrameworkIdentifier = *tfId;
+ }
+ if (cmValue tfTargetsVer = this->GeneratorTarget->GetProperty(
+ "VS_TARGET_FRAMEWORKS_TARGET_VERSION")) {
+ targetFrameworkTargetsVersion = *tfTargetsVer;
+ }
+ }
+ if (!targetFrameworkIdentifier) {
+ targetFrameworkIdentifier =
+ this->GlobalGenerator->GetTargetFrameworkIdentifier();
+ }
+ if (!targetFrameworkTargetsVersion) {
+ targetFrameworkTargetsVersion =
+ this->GlobalGenerator->GetTargetFrameworkTargetsVersion();
+ }
+ }
if (targetFramework) {
if (targetFramework->find(';') != std::string::npos) {
e1.Element("TargetFrameworks", *targetFramework);
} else {
e1.Element("TargetFramework", *targetFramework);
}
- } else {
- // TODO: add deprecation warning for VS_* property?
- cmProp p = this->GeneratorTarget->GetProperty(
- "VS_DOTNET_TARGET_FRAMEWORK_VERSION");
- if (!p) {
- p = this->GeneratorTarget->GetProperty(
- "DOTNET_TARGET_FRAMEWORK_VERSION");
- }
- const char* targetFrameworkVersion = cmToCStr(p);
- if (!targetFrameworkVersion && this->ProjectType == csproj &&
- this->GlobalGenerator->TargetsWindowsCE() &&
- this->GlobalGenerator->GetVersion() ==
- cmGlobalVisualStudioGenerator::VS12) {
- // VS12 .NETCF default to .NET framework 3.9
- targetFrameworkVersion = "v3.9";
- }
- if (targetFrameworkVersion) {
- e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
- }
}
- if (this->ProjectType == vcxproj &&
- this->GlobalGenerator->TargetsWindowsCE()) {
- e1.Element("EnableRedirectPlatform", "true");
- e1.Element("RedirectPlatformValue", this->Platform);
+ if (targetFrameworkVersion) {
+ e1.Element("TargetFrameworkVersion", *targetFrameworkVersion);
}
- if (this->ProjectType == csproj &&
- this->GlobalGenerator->TargetsWindowsCE()) {
- cmProp targetFrameworkId = this->GeneratorTarget->GetProperty(
- "VS_TARGET_FRAMEWORK_IDENTIFIER");
- e1.Element("TargetFrameworkIdentifier",
- targetFrameworkId ? *targetFrameworkId
- : "WindowsEmbeddedCompact");
- cmProp targetFrameworkVer = this->GeneratorTarget->GetProperty(
- "VS_TARGET_FRAMEWORKS_TARGET_VERSION");
+ if (targetFrameworkIdentifier) {
+ e1.Element("TargetFrameworkIdentifier", *targetFrameworkIdentifier);
+ }
+ if (targetFrameworkTargetsVersion) {
e1.Element("TargetFrameworkTargetsVersion",
- targetFrameworkVer ? *targetFrameworkVer : "v8.0");
+ *targetFrameworkTargetsVersion);
}
if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
.empty()) {
@@ -574,7 +590,7 @@ void cmVisualStudio10TargetGenerator::Generate()
globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
continue;
}
- cmProp value = this->GeneratorTarget->GetProperty(keyIt);
+ cmValue value = this->GeneratorTarget->GetProperty(keyIt);
if (!value)
continue;
e1.Element(globalKey, *value);
@@ -697,7 +713,7 @@ void cmVisualStudio10TargetGenerator::Generate()
props = VS10_CSharp_USER_PROPS;
break;
}
- if (cmProp p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
+ if (cmValue p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
props = *p;
}
if (!props.empty()) {
@@ -810,7 +826,7 @@ void cmVisualStudio10TargetGenerator::Generate()
void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
{
std::vector<std::string> packageReferences;
- if (cmProp vsPackageReferences =
+ if (cmValue vsPackageReferences =
this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) {
cmExpandList(*vsPackageReferences, packageReferences);
}
@@ -830,7 +846,7 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0)
void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
{
std::vector<std::string> references;
- if (cmProp vsDotNetReferences =
+ if (cmValue vsDotNetReferences =
this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) {
cmExpandList(*vsDotNetReferences, references);
}
@@ -889,7 +905,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
e2.Element("ReferenceOutputAssembly", "true");
if (!hint.empty()) {
const char* privateReference = "True";
- if (cmProp value = this->GeneratorTarget->GetProperty(
+ if (cmValue value = this->GeneratorTarget->GetProperty(
"VS_DOTNET_REFERENCES_COPY_LOCAL")) {
if (cmIsOff(*value)) {
privateReference = "False";
@@ -903,7 +919,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0)
{
- cmProp imports =
+ cmValue imports =
this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT");
if (imports) {
std::vector<std::string> argsSplit = cmExpandedList(*imports, false);
@@ -1007,7 +1023,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
".Designer.cs";
if (cmsys::SystemTools::FileExists(designerResource)) {
std::string generator = "PublicResXFileCodeGenerator";
- if (cmProp g = oi->GetProperty("VS_RESOURCE_GENERATOR")) {
+ if (cmValue g = oi->GetProperty("VS_RESOURCE_GENERATOR")) {
generator = *g;
}
if (!generator.empty()) {
@@ -1031,7 +1047,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
cm::string_view tagName =
cm::string_view(p).substr(propNamePrefix.length());
if (!tagName.empty()) {
- cmProp value = props.GetPropertyValue(p);
+ cmValue value = props.GetPropertyValue(p);
if (cmNonempty(value)) {
e2.Element(tagName, *value);
}
@@ -1050,7 +1066,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
for (cmSourceFile const* oi : this->XamlObjs) {
std::string obj = oi->GetFullPath();
std::string xamlType;
- cmProp xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
+ cmValue xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = *xamlTypeProperty;
} else {
@@ -1104,7 +1120,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
{
std::vector<std::string> references;
- if (cmProp vsWinRTReferences =
+ if (cmValue vsWinRTReferences =
this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) {
cmExpandList(*vsWinRTReferences, references);
}
@@ -1147,7 +1163,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
if (this->ProjectType != csproj) {
std::string configType;
- if (cmProp vsConfigurationType =
+ if (cmValue vsConfigurationType =
this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
configType = cmGeneratorExpression::Evaluate(*vsConfigurationType,
this->LocalGenerator, c);
@@ -1209,9 +1225,9 @@ void cmVisualStudio10TargetGenerator::WriteCEDebugProjectConfigurationValues(
if (!this->GlobalGenerator->TargetsWindowsCE()) {
return;
}
- cmProp additionalFiles =
+ cmValue additionalFiles =
this->GeneratorTarget->GetProperty("DEPLOYMENT_ADDITIONAL_FILES");
- cmProp remoteDirectory =
+ cmValue remoteDirectory =
this->GeneratorTarget->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY");
if (!(additionalFiles || remoteDirectory)) {
return;
@@ -1233,7 +1249,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
Elem& e1, std::string const& config)
{
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
- cmProp mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
+ cmValue mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue =
cmGeneratorExpression::Evaluate(*mfcFlag, this->LocalGenerator, config);
@@ -1263,7 +1279,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
} else {
e1.Element("CharacterSet", "MultiByte");
}
- if (cmProp projectToolsetOverride =
+ if (cmValue projectToolsetOverride =
this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
e1.Element("PlatformToolset", *projectToolsetOverride);
} else if (const char* toolset = gg->GetPlatformToolset()) {
@@ -1309,7 +1325,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
o.RemoveFlag("Platform");
}
- if (cmProp projectToolsetOverride =
+ if (cmValue projectToolsetOverride =
this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
e1.Element("PlatformToolset", *projectToolsetOverride);
} else if (const char* toolset = gg->GetPlatformToolset()) {
@@ -1320,7 +1336,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
std::string assemblyName = this->GeneratorTarget->GetOutputName(
config, cmStateEnums::RuntimeBinaryArtifact);
- if (cmProp postfix = this->GeneratorTarget->GetProperty(postfixName)) {
+ if (cmValue postfix = this->GeneratorTarget->GetProperty(postfixName)) {
assemblyName += *postfix;
}
e1.Element("AssemblyName", assemblyName);
@@ -1341,18 +1357,18 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
const char* toolset = gg->GetPlatformToolset();
e1.Element("NdkToolchainVersion", toolset ? toolset : "Default");
- if (cmProp minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
+ if (cmValue minApi = this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
e1.Element("AndroidMinAPI", "android-" + *minApi);
}
- if (cmProp api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
+ if (cmValue api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
e1.Element("AndroidTargetAPI", "android-" + *api);
}
- if (cmProp cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
+ if (cmValue cpuArch = this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
e1.Element("AndroidArch", *cpuArch);
}
- if (cmProp stlType =
+ if (cmValue stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
e1.Element("AndroidStlType", *stlType);
}
@@ -1362,13 +1378,13 @@ void cmVisualStudio10TargetGenerator::WriteAndroidConfigurationValues(
Elem& e1, std::string const&)
{
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
- if (cmProp projectToolsetOverride =
+ if (cmValue projectToolsetOverride =
this->GeneratorTarget->GetProperty("VS_PLATFORM_TOOLSET")) {
e1.Element("PlatformToolset", *projectToolsetOverride);
} else if (const char* toolset = gg->GetPlatformToolset()) {
e1.Element("PlatformToolset", toolset);
}
- if (cmProp stlType =
+ if (cmValue stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
if (*stlType != "none") {
e1.Element("UseOfStl", *stlType);
@@ -1472,7 +1488,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
cmCustomCommandGenerator ccg(command, c, lg, true);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
- std::string script = lg->ConstructScript(ccg);
+ cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed)
+ ? cmLocalVisualStudioGenerator::managed
+ : cmLocalVisualStudioGenerator::unmanaged;
+ std::string script = lg->ConstructScript(ccg, isManaged);
bool symbolic = false;
// input files for custom command
std::stringstream additional_inputs;
@@ -1803,8 +1822,8 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
}
}
-void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
- cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteHeaderSource(
+ Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings)
{
std::string const& fileName = sf->GetFullPath();
Elem e2(e1, "ClInclude");
@@ -1815,6 +1834,7 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
e2.Element("DependentUpon",
fileName.substr(0, fileName.find_last_of(".")));
}
+ this->FinishWritingSource(e2, toolSettings);
}
void cmVisualStudio10TargetGenerator::ParseSettingsProperty(
@@ -1871,8 +1891,8 @@ bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs(
return true;
}
-void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
- cmSourceFile const* sf)
+void cmVisualStudio10TargetGenerator::WriteExtraSource(
+ Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings)
{
bool toolHasSettings = false;
const char* tool = "None";
@@ -1883,10 +1903,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
std::string copyToOutDir;
std::string includeInVsix;
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
- ConfigToSettings toolSettings;
- for (const auto& config : this->Configurations) {
- toolSettings[config];
- }
if (this->ProjectType == csproj && !this->InSourceBuild) {
toolHasSettings = true;
@@ -1894,37 +1910,37 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
if (ext == "hlsl") {
tool = "FXCompile";
// Figure out the type of shader compiler to use.
- if (cmProp st = sf->GetProperty("VS_SHADER_TYPE")) {
+ if (cmValue st = sf->GetProperty("VS_SHADER_TYPE")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["ShaderType"] = *st;
}
}
// Figure out which entry point to use if any
- if (cmProp se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) {
+ if (cmValue se = sf->GetProperty("VS_SHADER_ENTRYPOINT")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["EntryPointName"] = *se;
}
}
// Figure out which shader model to use if any
- if (cmProp sm = sf->GetProperty("VS_SHADER_MODEL")) {
+ if (cmValue sm = sf->GetProperty("VS_SHADER_MODEL")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["ShaderModel"] = *sm;
}
}
// Figure out which output header file to use if any
- if (cmProp ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) {
+ if (cmValue ohf = sf->GetProperty("VS_SHADER_OUTPUT_HEADER_FILE")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["HeaderFileOutput"] = *ohf;
}
}
// Figure out which variable name to use if any
- if (cmProp vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) {
+ if (cmValue vn = sf->GetProperty("VS_SHADER_VARIABLE_NAME")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["VariableName"] = *vn;
}
}
// Figure out if there's any additional flags to use
- if (cmProp saf = sf->GetProperty("VS_SHADER_FLAGS")) {
+ if (cmValue saf = sf->GetProperty("VS_SHADER_FLAGS")) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*saf);
@@ -1937,7 +1953,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
// Figure out if debug information should be generated
- if (cmProp sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
+ if (cmValue sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sed);
@@ -1951,7 +1967,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
// Figure out if optimizations should be disabled
- if (cmProp sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
+ if (cmValue sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*sdo);
@@ -1964,7 +1980,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
}
- if (cmProp sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
+ if (cmValue sofn = sf->GetProperty("VS_SHADER_OBJECT_FILE_NAME")) {
for (const std::string& config : this->Configurations) {
toolSettings[config]["ObjectFileOutput"] = *sofn;
}
@@ -1987,7 +2003,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
} else if (ext == "vsixmanifest") {
subType = "Designer";
}
- if (cmProp c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
+ if (cmValue c = sf->GetProperty("VS_COPY_TO_OUT_DIR")) {
tool = "Content";
copyToOutDir = *c;
toolHasSettings = true;
@@ -2016,7 +2032,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
- cmProp toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
+ cmValue toolOverride = sf->GetProperty("VS_TOOL_OVERRIDE");
if (cmNonempty(toolOverride)) {
tool = toolOverride->c_str();
}
@@ -2025,12 +2041,12 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
std::string deployLocation;
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
- cmProp content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
+ cmValue content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
if (cmNonempty(content)) {
toolHasSettings = true;
deployContent = *content;
- cmProp location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
+ cmValue location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
if (cmNonempty(location)) {
deployLocation = *location;
}
@@ -2038,7 +2054,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) {
- cmProp toolTargetProperty = this->GeneratorTarget->Target->GetProperty(
+ cmValue toolTargetProperty = this->GeneratorTarget->Target->GetProperty(
"VS_SOURCE_SETTINGS_" + std::string(tool));
ConfigToSettings toolTargetSettings;
if (toolTargetProperty) {
@@ -2054,10 +2070,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
- if (cmProp p = sf->GetProperty("VS_SETTINGS")) {
- ParseSettingsProperty(*p, toolSettings);
- }
-
if (!toolSettings.empty()) {
toolHasSettings = true;
}
@@ -2067,27 +2079,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
if (toolHasSettings) {
e2.SetHasElements();
- std::vector<std::string> writtenSettings;
- for (const auto& configSettings : toolSettings) {
- for (const auto& setting : configSettings.second) {
-
- if (std::find(writtenSettings.begin(), writtenSettings.end(),
- setting.first) != writtenSettings.end()) {
- continue;
- }
-
- if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) {
- e2.Element(setting.first, setting.second);
- writtenSettings.push_back(setting.first);
- } else {
- e2.WritePlatformConfigTag(setting.first,
- "'$(Configuration)|$(Platform)'=='" +
- configSettings.first + "|" +
- this->Platform + "'",
- setting.second);
- }
- }
- }
+ this->FinishWritingSource(e2, toolSettings);
if (!deployContent.empty()) {
cmGeneratorExpression ge;
@@ -2224,6 +2216,15 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
// Skip explicit reference to CMakeLists.txt source.
continue;
}
+
+ ConfigToSettings toolSettings;
+ for (const auto& config : this->Configurations) {
+ toolSettings[config];
+ }
+ if (cmValue p = si.Source->GetProperty("VS_SETTINGS")) {
+ ParseSettingsProperty(*p, toolSettings);
+ }
+
const char* tool = nullptr;
switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
@@ -2251,10 +2252,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
}
break;
case cmGeneratorTarget::SourceKindExtra:
- this->WriteExtraSource(e1, si.Source);
+ this->WriteExtraSource(e1, si.Source, toolSettings);
break;
case cmGeneratorTarget::SourceKindHeader:
- this->WriteHeaderSource(e1, si.Source);
+ this->WriteHeaderSource(e1, si.Source, toolSettings);
break;
case cmGeneratorTarget::SourceKindIDL:
tool = "Midl";
@@ -2364,6 +2365,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
if (!isCSharp && !exclude_configs.empty()) {
this->WriteExcludeFromBuild(e2, exclude_configs);
}
+
+ this->FinishWritingSource(e2, toolSettings);
}
}
@@ -2372,6 +2375,32 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
}
}
+void cmVisualStudio10TargetGenerator::FinishWritingSource(
+ Elem& e2, ConfigToSettings const& toolSettings)
+{
+ std::vector<std::string> writtenSettings;
+ for (const auto& configSettings : toolSettings) {
+ for (const auto& setting : configSettings.second) {
+
+ if (std::find(writtenSettings.begin(), writtenSettings.end(),
+ setting.first) != writtenSettings.end()) {
+ continue;
+ }
+
+ if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) {
+ e2.Element(setting.first, setting.second);
+ writtenSettings.push_back(setting.first);
+ } else {
+ e2.WritePlatformConfigTag(setting.first,
+ "'$(Configuration)|$(Platform)'=='" +
+ configSettings.first + "|" +
+ this->Platform + "'",
+ setting.second);
+ }
+ }
+ }
+}
+
void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
Elem& e2, cmSourceFile const* source)
{
@@ -2389,22 +2418,22 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
bool configDependentDefines = false;
std::string includes;
bool configDependentIncludes = false;
- if (cmProp cflags = sf.GetProperty("COMPILE_FLAGS")) {
+ if (cmValue cflags = sf.GetProperty("COMPILE_FLAGS")) {
configDependentFlags =
cmGeneratorExpression::Find(*cflags) != std::string::npos;
flags += *cflags;
}
- if (cmProp coptions = sf.GetProperty("COMPILE_OPTIONS")) {
+ if (cmValue coptions = sf.GetProperty("COMPILE_OPTIONS")) {
configDependentOptions =
cmGeneratorExpression::Find(*coptions) != std::string::npos;
options += *coptions;
}
- if (cmProp cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
+ if (cmValue cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
configDependentDefines =
cmGeneratorExpression::Find(*cdefs) != std::string::npos;
defines += *cdefs;
}
- if (cmProp cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
+ if (cmValue cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
configDependentIncludes =
cmGeneratorExpression::Find(*cincludes) != std::string::npos;
includes += *cincludes;
@@ -2442,7 +2471,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
std::string configUpper = cmSystemTools::UpperCase(config);
std::string configDefines = defines;
std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
- if (cmProp ccdefs = sf.GetProperty(defPropName)) {
+ if (cmValue ccdefs = sf.GetProperty(defPropName)) {
if (!configDefines.empty()) {
configDefines += ";";
}
@@ -2618,7 +2647,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
const std::string cond = this->CalcCondition(config);
if (ttype <= cmStateEnums::UTILITY) {
- if (cmProp workingDir = this->GeneratorTarget->GetProperty(
+ if (cmValue workingDir = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_WORKING_DIRECTORY")) {
std::string genWorkingDir = cmGeneratorExpression::Evaluate(
*workingDir, this->LocalGenerator, config);
@@ -2626,7 +2655,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
genWorkingDir);
}
- if (cmProp environment =
+ if (cmValue environment =
this->GeneratorTarget->GetProperty("VS_DEBUGGER_ENVIRONMENT")) {
std::string genEnvironment = cmGeneratorExpression::Evaluate(
*environment, this->LocalGenerator, config);
@@ -2634,7 +2663,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
genEnvironment);
}
- if (cmProp debuggerCommand =
+ if (cmValue debuggerCommand =
this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
std::string genDebuggerCommand = cmGeneratorExpression::Evaluate(
*debuggerCommand, this->LocalGenerator, config);
@@ -2642,7 +2671,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
genDebuggerCommand);
}
- if (cmProp commandArguments = this->GeneratorTarget->GetProperty(
+ if (cmValue commandArguments = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_COMMAND_ARGUMENTS")) {
std::string genCommandArguments = cmGeneratorExpression::Evaluate(
*commandArguments, this->LocalGenerator, config);
@@ -2674,40 +2703,40 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
- if (cmProp sdkExecutableDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkExecutableDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
e1.WritePlatformConfigTag("ExecutablePath", cond,
*sdkExecutableDirectories);
}
- if (cmProp sdkIncludeDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkIncludeDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
e1.WritePlatformConfigTag("IncludePath", cond, *sdkIncludeDirectories);
}
- if (cmProp sdkReferenceDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkReferenceDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
e1.WritePlatformConfigTag("ReferencePath", cond,
*sdkReferenceDirectories);
}
- if (cmProp sdkLibraryDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkLibraryDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
e1.WritePlatformConfigTag("LibraryPath", cond, *sdkLibraryDirectories);
}
- if (cmProp sdkLibraryWDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkLibraryWDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
e1.WritePlatformConfigTag("LibraryWPath", cond,
*sdkLibraryWDirectories);
}
- if (cmProp sdkSourceDirectories =
+ if (cmValue sdkSourceDirectories =
this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
e1.WritePlatformConfigTag("SourcePath", cond, *sdkSourceDirectories);
}
- if (cmProp sdkExcludeDirectories = this->Makefile->GetDefinition(
+ if (cmValue sdkExcludeDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
e1.WritePlatformConfigTag("ExcludePath", cond, *sdkExcludeDirectories);
}
@@ -2905,7 +2934,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->Makefile->IssueMessage(MessageType::WARNING, message);
}
}
- if (cmProp clr =
+ if (cmValue clr =
this->GeneratorTarget->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
std::string clrString = *clr;
if (!clrString.empty()) {
@@ -3048,7 +3077,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
oh.OutputPreprocessorDefinitions(this->LangForClCompile);
if (this->NsightTegra) {
- if (cmProp processMax =
+ if (cmValue processMax =
this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
e2.Element("ProcessMax", *processMax);
}
@@ -3547,8 +3576,6 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
}
Elem e2(e1, "NASM");
- std::vector<std::string> includes =
- this->GetIncludes(configName, "ASM_NASM");
OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
nasmOptions.OutputFlagMap();
@@ -3608,7 +3635,7 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions(
std::vector<cmSourceFile const*> manifest_srcs;
this->GeneratorTarget->GetManifests(manifest_srcs, config);
- cmProp dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
+ cmValue dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE");
if (!manifest_srcs.empty() || dpiAware) {
Elem e2(e1, "Manifest");
@@ -3669,24 +3696,24 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
e2.Element("EnableProGuard", "true");
}
- if (cmProp proGuardConfigLocation =
+ if (cmValue proGuardConfigLocation =
this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
e2.Element("ProGuardConfigLocation", *proGuardConfigLocation);
}
- if (cmProp securePropertiesLocation =
+ if (cmValue securePropertiesLocation =
this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
e2.Element("SecurePropertiesLocation", *securePropertiesLocation);
}
- if (cmProp nativeLibDirectoriesExpression =
+ if (cmValue nativeLibDirectoriesExpression =
this->GeneratorTarget->GetProperty("ANDROID_NATIVE_LIB_DIRECTORIES")) {
std::string nativeLibDirs = cmGeneratorExpression::Evaluate(
*nativeLibDirectoriesExpression, this->LocalGenerator, configName);
e2.Element("NativeLibDirectories", nativeLibDirs);
}
- if (cmProp nativeLibDependenciesExpression =
+ if (cmValue nativeLibDependenciesExpression =
this->GeneratorTarget->GetProperty(
"ANDROID_NATIVE_LIB_DEPENDENCIES")) {
std::string nativeLibDeps = cmGeneratorExpression::Evaluate(
@@ -3694,24 +3721,24 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
e2.Element("NativeLibDependencies", nativeLibDeps);
}
- if (cmProp javaSourceDir =
+ if (cmValue javaSourceDir =
this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
e2.Element("JavaSourceDir", *javaSourceDir);
}
- if (cmProp jarDirectoriesExpression =
+ if (cmValue jarDirectoriesExpression =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DIRECTORIES")) {
std::string jarDirectories = cmGeneratorExpression::Evaluate(
*jarDirectoriesExpression, this->LocalGenerator, configName);
e2.Element("JarDirectories", jarDirectories);
}
- if (cmProp jarDeps =
+ if (cmValue jarDeps =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
e2.Element("JarDependencies", *jarDeps);
}
- if (cmProp assetsDirectories =
+ if (cmValue assetsDirectories =
this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
e2.Element("AssetsDirectories", *assetsDirectories);
}
@@ -3722,7 +3749,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
e2.Element("AndroidManifestLocation", manifest_xml);
}
- if (cmProp antAdditionalOptions =
+ if (cmValue antAdditionalOptions =
this->GeneratorTarget->GetProperty("ANDROID_ANT_ADDITIONAL_OPTIONS")) {
e2.Element("AdditionalOptions",
*antAdditionalOptions + " %(AdditionalOptions)");
@@ -3777,13 +3804,13 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
- cmProp targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
+ cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
flags += " ";
flags += *targetLinkFlags;
}
std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
- if (cmProp flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) {
+ if (cmValue flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) {
flags += " ";
flags += *flagsConfig;
}
@@ -3864,7 +3891,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
};
}
- if (cmProp stackVal = this->Makefile->GetDefinition(
+ if (cmValue stackVal = this->Makefile->GetDefinition(
"CMAKE_" + linkLanguage + "_STACK_SIZE")) {
linkOptions.AddFlag("StackReserveSize", *stackVal);
}
@@ -4214,7 +4241,10 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
comment += lg->ConstructComment(ccg);
script += pre;
pre = "\n";
- script += lg->ConstructScript(ccg);
+ cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed)
+ ? cmLocalVisualStudioGenerator::managed
+ : cmLocalVisualStudioGenerator::unmanaged;
+ script += lg->ConstructScript(ccg, isManaged);
stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8();
}
@@ -4262,7 +4292,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
std::string path;
- if (cmProp p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
+ if (cmValue p = dt->GetProperty("EXTERNAL_MSPROJECT")) {
path = *p;
} else {
path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
@@ -4292,13 +4322,13 @@ void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
// This only applies to Windows 10 apps
if (this->GlobalGenerator->TargetsWindowsStore() &&
cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
- cmProp desktopExtensionsVersion =
+ cmValue desktopExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
if (desktopExtensionsVersion) {
this->WriteSinglePlatformExtension(e1, "WindowsDesktop",
*desktopExtensionsVersion);
}
- cmProp mobileExtensionsVersion =
+ cmValue mobileExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
if (mobileExtensionsVersion) {
this->WriteSinglePlatformExtension(e1, "WindowsMobile",
@@ -4327,7 +4357,7 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
{
std::vector<std::string> sdkReferences;
std::unique_ptr<Elem> spe1;
- if (cmProp vsSDKReferences =
+ if (cmValue vsSDKReferences =
this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) {
cmExpandList(*vsSDKReferences, sdkReferences);
spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
@@ -4339,11 +4369,11 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
// This only applies to Windows 10 apps
if (this->GlobalGenerator->TargetsWindowsStore() &&
cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) {
- cmProp desktopExtensionsVersion =
+ cmValue desktopExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION");
- cmProp mobileExtensionsVersion =
+ cmValue mobileExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_MOBILE_EXTENSIONS_VERSION");
- cmProp iotExtensionsVersion =
+ cmValue iotExtensionsVersion =
this->GeneratorTarget->GetProperty("VS_IOT_EXTENSIONS_VERSION");
if (desktopExtensionsVersion || mobileExtensionsVersion ||
@@ -4553,7 +4583,7 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1)
if (!targetPlatformVersion.empty()) {
e1.Element("WindowsTargetPlatformVersion", targetPlatformVersion);
}
- cmProp targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
+ cmValue targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
"VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
if (targetPlatformMinVersion) {
e1.Element("WindowsTargetPlatformMinVersion", *targetPlatformMinVersion);
@@ -5049,7 +5079,7 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
if (cmHasPrefix(p, propNamePrefix)) {
std::string tagName = p.substr(propNamePrefix.length());
if (!tagName.empty()) {
- cmProp val = props.GetPropertyValue(p);
+ cmValue val = props.GetPropertyValue(p);
if (cmNonempty(val)) {
tags[tagName] = *val;
} else {
@@ -5101,7 +5131,7 @@ std::string cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
} else if (!cmHasSuffix(fullFileName, ".cs") &&
cmHasPrefix(fullFileName, binDir)) {
link = fullFileName.substr(binDir.length() + 1);
- } else if (cmProp l = source->GetProperty("VS_CSHARP_Link")) {
+ } else if (cmValue l = source->GetProperty("VS_CSHARP_Link")) {
link = *l;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 55c5444f1..a5ce5e58f 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -58,6 +58,10 @@ private:
struct Elem;
struct OptionsHelper;
+ using ConfigToSettings =
+ std::unordered_map<std::string,
+ std::unordered_map<std::string, std::string>>;
+
std::string ConvertPath(std::string const& path, bool forceRelative);
std::string CalcCondition(const std::string& config) const;
void WriteProjectConfigurations(Elem& e0);
@@ -66,12 +70,15 @@ private:
void WriteCEDebugProjectConfigurationValues(Elem& e0);
void WriteMSToolConfigurationValuesManaged(Elem& e1,
std::string const& config);
- void WriteHeaderSource(Elem& e1, cmSourceFile const* sf);
- void WriteExtraSource(Elem& e1, cmSourceFile const* sf);
+ void WriteHeaderSource(Elem& e1, cmSourceFile const* sf,
+ ConfigToSettings const& toolSettings);
+ void WriteExtraSource(Elem& e1, cmSourceFile const* sf,
+ ConfigToSettings& toolSettings);
void WriteNsightTegraConfigurationValues(Elem& e1,
std::string const& config);
void WriteAndroidConfigurationValues(Elem& e1, std::string const& config);
void WriteSource(Elem& e2, cmSourceFile const* sf);
+ void FinishWritingSource(Elem& e2, ConfigToSettings const& toolSettings);
void WriteExcludeFromBuild(Elem& e2,
std::vector<size_t> const& exclude_configs);
void WriteAllSources(Elem& e0);
@@ -252,9 +259,6 @@ private:
void ClassifyAllConfigSources();
void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs);
- using ConfigToSettings =
- std::unordered_map<std::string,
- std::unordered_map<std::string, std::string>>;
std::unordered_map<std::string, ConfigToSettings> ParsedToolTargetSettings;
bool PropertyIsSameInAllConfigs(const ConfigToSettings& toolSettings,
const std::string& propName);
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 327c1c7ba..b8297ce21 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -16,13 +16,14 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmOutputConverter.h"
#include "cmSystemTools.h"
#include "cmake.h"
class cmWhileFunctionBlocker : public cmFunctionBlocker
{
public:
- cmWhileFunctionBlocker(cmMakefile* mf);
+ cmWhileFunctionBlocker(cmMakefile* mf, std::vector<cmListFileArgument> args);
~cmWhileFunctionBlocker() override;
cm::string_view StartCommandName() const override { return "while"_s; }
@@ -34,14 +35,15 @@ public:
bool Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& inStatus) override;
- std::vector<cmListFileArgument> Args;
-
private:
cmMakefile* Makefile;
+ std::vector<cmListFileArgument> Args;
};
-cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
- : Makefile(mf)
+cmWhileFunctionBlocker::cmWhileFunctionBlocker(
+ cmMakefile* const mf, std::vector<cmListFileArgument> args)
+ : Makefile{ mf }
+ , Args{ std::move(args) }
{
this->Makefile->PushLoopBlock();
}
@@ -60,39 +62,29 @@ bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
cmExecutionStatus& inStatus)
{
- cmMakefile& mf = inStatus.GetMakefile();
- std::string errorString;
-
- std::vector<cmExpandedCommandArgument> expandedArguments;
- mf.ExpandArguments(this->Args, expandedArguments);
- MessageType messageType;
+ auto& mf = inStatus.GetMakefile();
cmListFileBacktrace whileBT =
mf.GetBacktrace().Push(this->GetStartingContext());
- cmConditionEvaluator conditionEvaluator(mf, whileBT);
-
- bool isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
-
- while (isTrue) {
- if (!errorString.empty()) {
- std::string err = "had incorrect arguments: ";
- for (cmListFileArgument const& arg : this->Args) {
- err += (arg.Delim ? "\"" : "");
- err += arg.Value;
- err += (arg.Delim ? "\"" : "");
- err += " ";
- }
- err += "(";
- err += errorString;
- err += ").";
- mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT);
- if (messageType == MessageType::FATAL_ERROR) {
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
- }
+ std::vector<cmExpandedCommandArgument> expandedArguments;
+ // At least same size expected for `expandedArguments` as `Args`
+ expandedArguments.reserve(this->Args.size());
+
+ auto expandArgs = [&mf](std::vector<cmListFileArgument> const& args,
+ std::vector<cmExpandedCommandArgument>& out)
+ -> std::vector<cmExpandedCommandArgument>& {
+ out.clear();
+ mf.ExpandArguments(args, out);
+ return out;
+ };
+
+ std::string errorString;
+ MessageType messageType;
+
+ for (cmConditionEvaluator conditionEvaluator(mf, whileBT);
+ conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments),
+ errorString, messageType);) {
// Invoke all the functions that were collected in the block.
for (cmListFileFunction const& fn : functions) {
cmExecutionStatus status(mf);
@@ -111,11 +103,22 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
return true;
}
}
- expandedArguments.clear();
- mf.ExpandArguments(this->Args, expandedArguments);
- isTrue =
- conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);
}
+
+ if (!errorString.empty()) {
+ std::string err = "had incorrect arguments:\n ";
+ for (auto const& i : expandedArguments) {
+ err += " ";
+ err += cmOutputConverter::EscapeForCMake(i.GetValue());
+ }
+ err += "\n";
+ err += errorString;
+ mf.GetCMakeInstance()->IssueMessage(messageType, err, whileBT);
+ if (messageType == MessageType::FATAL_ERROR) {
+ cmSystemTools::SetFatalErrorOccured();
+ }
+ }
+
return true;
}
@@ -128,11 +131,9 @@ bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
}
// create a function blocker
- {
- cmMakefile& makefile = status.GetMakefile();
- auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile);
- fb->Args = args;
- makefile.AddFunctionBlocker(std::move(fb));
- }
+ auto& makefile = status.GetMakefile();
+ makefile.AddFunctionBlocker(
+ cm::make_unique<cmWhileFunctionBlocker>(&makefile, args));
+
return true;
}
diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h
index ff255261d..403565016 100644
--- a/Source/cmWorkerPool.h
+++ b/Source/cmWorkerPool.h
@@ -87,7 +87,7 @@ public:
* Get the user data.
* Only valid during the JobT::Process() call!
*/
- void* UserData() const { return this->Pool_->UserData(); };
+ void* UserData() const { return this->Pool_->UserData(); }
/**
* Get the worker index.
@@ -138,7 +138,7 @@ public:
{
}
//! Does nothing
- void Process() override{};
+ void Process() override {}
};
/**
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index e4329afc6..e2c0f2daf 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -204,7 +204,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
// Info tab begin
- if (cmProp exe =
+ if (cmValue exe =
this->Target->GetTarget()->GetProperty("XCODE_SCHEME_EXECUTABLE")) {
xout.StartElement("PathRunnable");
@@ -220,7 +220,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
// Arguments tab begin
- if (cmProp argList =
+ if (cmValue argList =
this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) {
std::vector<std::string> arguments = cmExpandedList(*argList);
if (!arguments.empty()) {
@@ -240,7 +240,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
}
}
- if (cmProp envList =
+ if (cmValue envList =
this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) {
std::vector<std::string> envs = cmExpandedList(*envList);
if (!envs.empty()) {
@@ -323,7 +323,7 @@ bool cmXCodeScheme::WriteLaunchActionBooleanAttribute(
cmXMLWriter& xout, const std::string& attrName, const std::string& varName,
bool defaultValue)
{
- cmProp property = Target->GetTarget()->GetProperty(varName);
+ cmValue property = Target->GetTarget()->GetProperty(varName);
bool isOn = (!property && defaultValue) || cmIsOn(property);
if (isOn) {
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 73f5ad5b8..fda790091 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -114,7 +114,9 @@
# include "cmExtraSublimeTextGenerator.h"
#endif
-#if defined(__linux__) || defined(_WIN32)
+// NOTE: the __linux__ macro is predefined on Android host too, but
+// main CMakeLists.txt filters out this generator by host name.
+#if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32)
# include "cmGlobalGhsMultiGenerator.h"
#endif
@@ -156,17 +158,16 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
}
#endif
-cmake::cmake(Role role, cmState::Mode mode)
+cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind)
: CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory())
, FileTimeCache(cm::make_unique<cmFileTimeCache>())
#ifndef CMAKE_BOOTSTRAP
, VariableWatch(cm::make_unique<cmVariableWatch>())
#endif
- , State(cm::make_unique<cmState>())
+ , State(cm::make_unique<cmState>(mode, projectKind))
, Messenger(cm::make_unique<cmMessenger>())
{
this->TraceFile.close();
- this->State->SetMode(mode);
this->CurrentSnapshot = this->State->CreateBaseSnapshot();
#ifdef __APPLE__
@@ -598,15 +599,14 @@ void cmake::ProcessCacheArg(const std::string& var, const std::string& value,
bool haveValue = false;
std::string cachedValue;
if (this->WarnUnusedCli) {
- if (cmProp v = this->State->GetInitializedCacheValue(var)) {
+ if (cmValue v = this->State->GetInitializedCacheValue(var)) {
haveValue = true;
cachedValue = *v;
}
}
- this->AddCacheEntry(var, value.c_str(),
- "No help, variable specified on the command line.",
- type);
+ this->AddCacheEntry(
+ var, value, "No help, variable specified on the command line.", type);
if (this->WarnUnusedCli) {
if (!haveValue ||
@@ -1468,7 +1468,7 @@ void cmake::SetDirectoriesFromFile(const std::string& arg)
// If there is a CMakeCache.txt file, use its settings.
if (!cachePath.empty()) {
if (this->LoadCache(cachePath)) {
- cmProp existingValue =
+ cmValue existingValue =
this->State->GetCacheEntryValue("CMAKE_HOME_DIRECTORY");
if (existingValue) {
this->SetHomeOutputDirectory(cachePath);
@@ -1516,16 +1516,15 @@ void cmake::SetDirectoriesFromFile(const std::string& arg)
int cmake::AddCMakePaths()
{
// Save the value in the cache
- this->AddCacheEntry("CMAKE_COMMAND",
- cmSystemTools::GetCMakeCommand().c_str(),
+ this->AddCacheEntry("CMAKE_COMMAND", cmSystemTools::GetCMakeCommand(),
"Path to CMake executable.", cmStateEnums::INTERNAL);
#ifndef CMAKE_BOOTSTRAP
- this->AddCacheEntry(
- "CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(),
- "Path to ctest program executable.", cmStateEnums::INTERNAL);
- this->AddCacheEntry(
- "CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand().c_str(),
- "Path to cpack program executable.", cmStateEnums::INTERNAL);
+ this->AddCacheEntry("CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand(),
+ "Path to ctest program executable.",
+ cmStateEnums::INTERNAL);
+ this->AddCacheEntry("CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand(),
+ "Path to cpack program executable.",
+ cmStateEnums::INTERNAL);
#endif
if (!cmSystemTools::FileExists(
(cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake"))) {
@@ -1537,7 +1536,7 @@ int cmake::AddCMakePaths()
cmSystemTools::GetCMakeRoot());
return 0;
}
- this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(),
+ this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot(),
"Path to CMake installation.", cmStateEnums::INTERNAL);
return 1;
@@ -1843,7 +1842,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
std::vector<std::string> argsSplit = cmExpandedList(var, true);
// erase the property to avoid infinite recursion
this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
- if (this->State->GetIsInTryCompile()) {
+ if (this->GetIsInTryCompile()) {
return 0;
}
std::vector<SaveCacheEntry> saved;
@@ -1866,10 +1865,10 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
warning << "\n";
i -= 1;
}
- cmProp existingValue = this->State->GetCacheEntryValue(save.key);
+ cmValue existingValue = this->State->GetCacheEntryValue(save.key);
if (existingValue) {
save.type = this->State->GetCacheEntryType(save.key);
- if (cmProp help =
+ if (cmValue help =
this->State->GetCacheEntryProperty(save.key, "HELPSTRING")) {
save.help = *help;
}
@@ -1885,7 +1884,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
this->LoadCache();
// restore the changed compilers
for (SaveCacheEntry const& i : saved) {
- this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type);
+ this->AddCacheEntry(i.key, i.value, i.help.c_str(), i.type);
}
cmSystemTools::Message(warning.str());
// avoid reconfigure if there were errors
@@ -1918,9 +1917,9 @@ int cmake::Configure()
if (this->DiagLevels.count("dev") == 1) {
bool setDeprecatedVariables = false;
- cmProp cachedWarnDeprecated =
+ cmValue cachedWarnDeprecated =
this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
- cmProp cachedErrorDeprecated =
+ cmValue cachedErrorDeprecated =
this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
// don't overwrite deprecated warning setting from a previous invocation
@@ -1959,7 +1958,7 @@ int cmake::Configure()
// Cache variables may have already been set by a previous invocation,
// so we cannot rely on command line options alone. Always ensure our
// messenger is in sync with the cache.
- cmProp value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
+ cmValue value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED");
this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(*value));
value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED");
@@ -1972,7 +1971,7 @@ int cmake::Configure()
this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(*value));
int ret = this->ActualConfigure();
- cmProp delCacheVars =
+ cmValue delCacheVars =
this->State->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_");
if (delCacheVars && !delCacheVars->empty()) {
return this->HandleDeleteCacheVariables(*delCacheVars);
@@ -1992,7 +1991,7 @@ int cmake::ActualConfigure()
}
if (!res) {
this->AddCacheEntry(
- "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory().c_str(),
+ "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory(),
"Source directory with the top level CMakeLists.txt file for this "
"project",
cmStateEnums::INTERNAL);
@@ -2000,8 +1999,8 @@ int cmake::ActualConfigure()
// no generator specified on the command line
if (!this->GlobalGenerator) {
- cmProp genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
- cmProp extraGenName =
+ cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
+ cmValue extraGenName =
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
if (genName) {
std::string fullName =
@@ -2024,7 +2023,7 @@ int cmake::ActualConfigure()
}
}
- cmProp genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
+ cmValue genName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
if (genName) {
if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) {
std::string message =
@@ -2037,26 +2036,24 @@ int cmake::ActualConfigure()
}
}
if (!this->State->GetInitializedCacheValue("CMAKE_GENERATOR")) {
- this->AddCacheEntry("CMAKE_GENERATOR",
- this->GlobalGenerator->GetName().c_str(),
+ this->AddCacheEntry("CMAKE_GENERATOR", this->GlobalGenerator->GetName(),
"Name of generator.", cmStateEnums::INTERNAL);
- this->AddCacheEntry("CMAKE_EXTRA_GENERATOR",
- this->GlobalGenerator->GetExtraGeneratorName().c_str(),
- "Name of external makefile project generator.",
- cmStateEnums::INTERNAL);
+ this->AddCacheEntry(
+ "CMAKE_EXTRA_GENERATOR", this->GlobalGenerator->GetExtraGeneratorName(),
+ "Name of external makefile project generator.", cmStateEnums::INTERNAL);
if (!this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) {
std::string envToolchain;
if (cmSystemTools::GetEnv("CMAKE_TOOLCHAIN_FILE", envToolchain) &&
!envToolchain.empty()) {
- this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain.c_str(),
+ this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain,
"The CMake toolchain file",
cmStateEnums::FILEPATH);
}
}
}
- if (cmProp instance =
+ if (cmValue instance =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
std::string message =
@@ -2068,12 +2065,12 @@ int cmake::ActualConfigure()
return -2;
}
} else {
- this->AddCacheEntry(
- "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(),
- "Generator instance identifier.", cmStateEnums::INTERNAL);
+ this->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance,
+ "Generator instance identifier.",
+ cmStateEnums::INTERNAL);
}
- if (cmProp platformName =
+ if (cmValue platformName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
if (this->GeneratorPlatformSet &&
this->GeneratorPlatform != *platformName) {
@@ -2086,12 +2083,11 @@ int cmake::ActualConfigure()
return -2;
}
} else {
- this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM",
- this->GeneratorPlatform.c_str(),
+ this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform,
"Name of generator platform.", cmStateEnums::INTERNAL);
}
- if (cmProp tsName =
+ if (cmValue tsName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
std::string message =
@@ -2103,15 +2099,14 @@ int cmake::ActualConfigure()
return -2;
}
} else {
- this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
- this->GeneratorToolset.c_str(),
+ this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset,
"Name of generator toolset.", cmStateEnums::INTERNAL);
}
// reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time
- if (!this->State->GetIsInTryCompile()) {
+ if (!this->GetIsInTryCompile()) {
this->GlobalGenerator->ClearEnabledLanguages();
this->TruncateOutputLog("CMakeOutput.log");
@@ -2415,7 +2410,7 @@ int cmake::Generate()
return 0;
}
-void cmake::AddCacheEntry(const std::string& key, const char* value,
+void cmake::AddCacheEntry(const std::string& key, cmValue value,
const char* helpString, int type)
{
this->State->AddCacheEntry(key, value, helpString,
@@ -2491,7 +2486,7 @@ std::string cmake::StripExtension(const std::string& file) const
return file;
}
-cmProp cmake::GetCacheDefinition(const std::string& name) const
+cmValue cmake::GetCacheDefinition(const std::string& name) const
{
return this->State->GetInitializedCacheValue(name);
}
@@ -2529,7 +2524,7 @@ void cmake::AddDefaultGenerators()
this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
#if !defined(CMAKE_BOOTSTRAP)
-# if defined(__linux__) || defined(_WIN32)
+# if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32)
this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory());
# endif
this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory());
@@ -2622,19 +2617,14 @@ void cmake::SetProgressCallback(ProgressCallbackType f)
void cmake::UpdateProgress(const std::string& msg, float prog)
{
- if (this->ProgressCallback && !this->State->GetIsInTryCompile()) {
+ if (this->ProgressCallback && !this->GetIsInTryCompile()) {
this->ProgressCallback(msg, prog);
}
}
bool cmake::GetIsInTryCompile() const
{
- return this->State->GetIsInTryCompile();
-}
-
-void cmake::SetIsInTryCompile(bool b)
-{
- this->State->SetIsInTryCompile(b);
+ return this->State->GetProjectKind() == cmState::ProjectKind::TryCompile;
}
void cmake::AppendGlobalGeneratorsDocumentation(
@@ -2705,7 +2695,7 @@ void cmake::PrintGeneratorList()
void cmake::UpdateConversionPathTable()
{
// Update the path conversion table with any specified file:
- cmProp tablepath =
+ cmValue tablepath =
this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE");
if (tablepath) {
@@ -2923,6 +2913,10 @@ void cmake::SetProperty(const std::string& prop, const char* value)
{
this->State->SetGlobalProperty(prop, value);
}
+void cmake::SetProperty(const std::string& prop, cmValue value)
+{
+ this->State->SetGlobalProperty(prop, value);
+}
void cmake::AppendProperty(const std::string& prop, const std::string& value,
bool asString)
@@ -2930,7 +2924,7 @@ void cmake::AppendProperty(const std::string& prop, const std::string& value,
this->State->AppendGlobalProperty(prop, value, asString);
}
-cmProp cmake::GetProperty(const std::string& prop)
+cmValue cmake::GetProperty(const std::string& prop)
{
return this->State->GetGlobalProperty(prop);
}
@@ -3175,7 +3169,7 @@ void cmake::IssueMessage(MessageType t, std::string const& text,
std::vector<std::string> cmake::GetDebugConfigs()
{
std::vector<std::string> configs;
- if (cmProp config_list =
+ if (cmValue config_list =
this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) {
// Expand the specified list and convert to upper-case.
cmExpandList(*config_list, configs);
@@ -3324,7 +3318,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
std::cerr << "Error: could not load cache\n";
return 1;
}
- cmProp cachedGenerator = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
+ cmValue cachedGenerator = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
if (!cachedGenerator) {
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
@@ -3336,7 +3330,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
this->SetGlobalGenerator(std::move(gen));
- cmProp cachedGeneratorInstance =
+ cmValue cachedGeneratorInstance =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
if (cachedGeneratorInstance) {
cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot());
@@ -3345,7 +3339,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
}
- cmProp cachedGeneratorPlatform =
+ cmValue cachedGeneratorPlatform =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_PLATFORM");
if (cachedGeneratorPlatform) {
cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot());
@@ -3354,7 +3348,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
return 1;
}
}
- cmProp cachedGeneratorToolset =
+ cmValue cachedGeneratorToolset =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_TOOLSET");
if (cachedGeneratorToolset) {
cmMakefile mf(this->GetGlobalGenerator(), this->GetCurrentSnapshot());
@@ -3365,7 +3359,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
}
std::string output;
std::string projName;
- cmProp cachedProjectName =
+ cmValue cachedProjectName =
this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
if (!cachedProjectName) {
std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
@@ -3457,12 +3451,12 @@ bool cmake::Open(const std::string& dir, bool dryRun)
std::cerr << "Error: could not load cache\n";
return false;
}
- cmProp genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
+ cmValue genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
if (!genName) {
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return false;
}
- cmProp extraGenName =
+ cmValue extraGenName =
this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
std::string fullName =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
@@ -3476,7 +3470,7 @@ bool cmake::Open(const std::string& dir, bool dryRun)
return false;
}
- cmProp cachedProjectName =
+ cmValue cachedProjectName =
this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
if (!cachedProjectName) {
std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
@@ -3540,7 +3534,7 @@ void cmake::SetSuppressDevWarnings(bool b)
value = "FALSE";
}
- this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value.c_str(),
+ this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value,
"Suppress Warnings that are meant for"
" the author of the CMakeLists.txt files.",
cmStateEnums::INTERNAL);
@@ -3564,7 +3558,7 @@ void cmake::SetSuppressDeprecatedWarnings(bool b)
value = "TRUE";
}
- this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value.c_str(),
+ this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value,
"Whether to issue warnings for deprecated "
"functionality.",
cmStateEnums::INTERNAL);
@@ -3588,7 +3582,7 @@ void cmake::SetDevWarningsAsErrors(bool b)
value = "TRUE";
}
- this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value.c_str(),
+ this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value,
"Suppress errors that are meant for"
" the author of the CMakeLists.txt files.",
cmStateEnums::INTERNAL);
@@ -3612,7 +3606,7 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b)
value = "FALSE";
}
- this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value.c_str(),
+ this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value,
"Whether to issue deprecation errors for macros"
" and functions.",
cmStateEnums::INTERNAL);
diff --git a/Source/cmake.h b/Source/cmake.h
index 5a2a88fac..3f2b2eda4 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -21,10 +21,10 @@
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
#include "cmMessageType.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
+#include "cmValue.h"
#if !defined(CMAKE_BOOTSTRAP)
# include <cm/optional>
@@ -168,7 +168,8 @@ public:
static const int DEFAULT_BUILD_PARALLEL_LEVEL = 0;
/// Default constructor
- cmake(Role role, cmState::Mode mode);
+ cmake(Role role, cmState::Mode mode,
+ cmState::ProjectKind projectKind = cmState::ProjectKind::Normal);
/// Destructor
~cmake();
@@ -328,9 +329,21 @@ public:
/**
* Given a variable name, return its value (as a string).
*/
- cmProp GetCacheDefinition(const std::string&) const;
+ cmValue GetCacheDefinition(const std::string&) const;
//! Add an entry into the cache
void AddCacheEntry(const std::string& key, const char* value,
+ const char* helpString, int type)
+ {
+ this->AddCacheEntry(key,
+ value ? cmValue(std::string(value)) : cmValue(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, int type)
+ {
+ this->AddCacheEntry(key, cmValue(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmValue value,
const char* helpString, int type);
bool DoWriteGlobVerifyTarget() const;
@@ -356,7 +369,6 @@ public:
//! Is this cmake running as a result of a TRY_COMPILE command
bool GetIsInTryCompile() const;
- void SetIsInTryCompile(bool b);
#ifndef CMAKE_BOOTSTRAP
void SetWarningFromPreset(const std::string& name,
@@ -396,9 +408,14 @@ public:
//! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmValue value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmValue(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
- cmProp GetProperty(const std::string& prop);
+ cmValue GetProperty(const std::string& prop);
bool GetPropertyAsBool(const std::string& prop);
//! Get or create an cmInstalledFile instance and return a pointer to it
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 95ad32048..61d4ae486 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -25,11 +25,11 @@
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageMetadata.h"
-#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmValue.h"
#include "cmake.h"
#include "cmcmd.h"
@@ -161,11 +161,11 @@ void cmakemainMessageCallback(const std::string& m,
// cannot use it to print messages. Another implementation will
// be needed to print colored messages on Windows.
static_cast<void>(md);
- std::cerr << m << cmakemainGetStack(cm) << '\n' << std::flush;
+ std::cerr << m << cmakemainGetStack(cm) << "\n";
#else
cmsysTerminal_cfprintf(md.desiredColor, stderr, "%s", m.c_str());
fflush(stderr); // stderr is buffered in some cases.
- std::cerr << cmakemainGetStack(cm) << '\n' << std::flush;
+ std::cerr << cmakemainGetStack(cm) << "\n";
#endif
}
@@ -375,11 +375,11 @@ int do_cmake(int ac, char const* const* av)
cmStateEnums::CacheEntryType t = cm.GetState()->GetCacheEntryType(k);
if (t != cmStateEnums::INTERNAL && t != cmStateEnums::STATIC &&
t != cmStateEnums::UNINITIALIZED) {
- cmProp advancedProp =
+ cmValue advancedProp =
cm.GetState()->GetCacheEntryProperty(k, "ADVANCED");
if (list_all_cached || !advancedProp) {
if (list_help) {
- cmProp help =
+ cmValue help =
cm.GetState()->GetCacheEntryProperty(k, "HELPSTRING");
std::cout << "// " << (help ? *help : "") << std::endl;
}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index db45add4f..bdddc4e78 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -23,6 +23,7 @@
#include "cmTransformDepfile.h"
#include "cmUVProcessChain.h"
#include "cmUtils.hxx"
+#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"
@@ -385,18 +386,15 @@ int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
return ret;
}
-int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */,
+int HandleLWYU(const std::string& runCmd, const std::string& sourceFile,
const std::vector<std::string>&)
{
// Construct the ldd -r -u (link what you use lwyu) command line
// ldd -u -r lwuy target
- std::vector<std::string> lwyu_cmd;
- lwyu_cmd.emplace_back("ldd");
- lwyu_cmd.emplace_back("-u");
- lwyu_cmd.emplace_back("-r");
- lwyu_cmd.push_back(runCmd);
+ std::vector<std::string> lwyu_cmd = cmExpandedList(runCmd, true);
+ lwyu_cmd.push_back(sourceFile);
- // Run the ldd -u -r command line.
+ // Run the lwyu check command line, currently ldd is expected.
// Capture its stdout and hide its stderr.
// Ignore its return code because the tool always returns non-zero
// if there are any warnings, but we just want to warn.
@@ -1071,6 +1069,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
} else if (!cmSystemTools::FileExists(arg)) {
cmSystemTools::Error(arg + ": no such file or directory (ignoring)");
return_value = 1;
+ } else if (cmSystemTools::FileLength(arg) == 0) {
+ // Ignore empty files, this is not an error
} else {
// Destroy console buffers to drop cout/cerr encoding transform.
consoleBuf.reset();
diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in
index ed46d5c2b..16efaefdf 100644
--- a/Source/kwsys/Status.hxx.in
+++ b/Source/kwsys/Status.hxx.in
@@ -55,7 +55,10 @@ public:
#endif
/** Return true on "Success", false otherwise. */
- explicit operator bool() const { return this->Kind_ == Kind::Success; }
+ bool IsSuccess() const { return this->Kind_ == Kind::Success; }
+
+ /** Return true on "Success", false otherwise. */
+ explicit operator bool() const { return this->IsSuccess(); }
/** Return the kind of status. */
Kind GetKind() const { return this->Kind_; }
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 12f9139cc..f2bf85f6a 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1356,14 +1356,12 @@ std::string SymbolProperties::Demangle(const char* symbol) const
std::string result = safes(symbol);
# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
int status = 0;
- size_t bufferLen = 1024;
- char* buffer = (char*)malloc(1024);
char* demangledSymbol =
- abi::__cxa_demangle(symbol, buffer, &bufferLen, &status);
+ abi::__cxa_demangle(symbol, nullptr, nullptr, &status);
if (!status) {
result = demangledSymbol;
}
- free(buffer);
+ free(demangledSymbol);
# else
(void)symbol;
# endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index f610a7050..930d84c87 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2423,7 +2423,7 @@ Status SystemTools::CopyFileAlways(std::string const& source,
if (SystemTools::FileIsDirectory(source)) {
status = SystemTools::MakeDirectory(destination);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
} else {
@@ -2448,17 +2448,17 @@ Status SystemTools::CopyFileAlways(std::string const& source,
// Create destination directory
if (!destination_dir.empty()) {
status = SystemTools::MakeDirectory(destination_dir);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
}
status = SystemTools::CloneFileContent(source, real_destination);
// if cloning did not succeed, fall back to blockwise copy
- if (!status) {
+ if (!status.IsSuccess()) {
status = SystemTools::CopyFileContentBlockwise(source, real_destination);
}
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
}
@@ -2488,11 +2488,11 @@ Status SystemTools::CopyADirectory(std::string const& source,
Status status;
Directory dir;
status = dir.Load(source);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
status = SystemTools::MakeDirectory(destination);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
@@ -2507,12 +2507,12 @@ Status SystemTools::CopyADirectory(std::string const& source,
fullDestPath += "/";
fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum));
status = SystemTools::CopyADirectory(fullPath, fullDestPath, always);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
} else {
status = SystemTools::CopyAFile(fullPath, destination, always);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
}
@@ -2664,7 +2664,7 @@ Status SystemTools::RemoveADirectory(std::string const& source)
Status status;
Directory dir;
status = dir.Load(source);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
@@ -2678,12 +2678,12 @@ Status SystemTools::RemoveADirectory(std::string const& source)
if (SystemTools::FileIsDirectory(fullPath) &&
!SystemTools::FileIsSymlink(fullPath)) {
status = SystemTools::RemoveADirectory(fullPath);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
} else {
status = SystemTools::RemoveFile(fullPath);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
}
@@ -3147,7 +3147,7 @@ Status SystemTools::ReadSymlink(std::string const& newName,
status = Status::Windows_GetLastError();
}
CloseHandle(hFile);
- if (!status) {
+ if (!status.IsSuccess()) {
return status;
}
PREPARSE_DATA_BUFFER data =
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index 06a22dc47..a847462a3 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -122,7 +122,7 @@ int _copyDirectoryTest()
}
const Status copysuccess = SystemTools::CopyADirectory(source, destination);
const bool destinationexists = SystemTools::PathExists(destination);
- if (copysuccess) {
+ if (copysuccess.IsSuccess()) {
std::cerr << "CopyADirectory should have returned false" << std::endl;
SystemTools::RemoveADirectory(destination);
return 3;
diff --git a/Source/kwsys/testStatus.cxx b/Source/kwsys/testStatus.cxx
index f85ef422d..0a767a854 100644
--- a/Source/kwsys/testStatus.cxx
+++ b/Source/kwsys/testStatus.cxx
@@ -31,6 +31,10 @@ int testStatus(int, char* [])
std::cerr << "Status Success constructor does not produce Success\n";
res = false;
}
+ if (!status.IsSuccess()) {
+ std::cerr << "Status Success gives false IsSuccess\n";
+ res = false;
+ }
if (!status) {
std::cerr << "Status Success kind is not true\n";
res = false;
@@ -55,6 +59,10 @@ int testStatus(int, char* [])
std::cerr << "Status POSIX constructor does not produce POSIX\n";
res = false;
}
+ if (status.IsSuccess()) {
+ std::cerr << "Status POSIX gives true IsSuccess\n";
+ res = false;
+ }
if (status) {
std::cerr << "Status POSIX kind is not false\n";
res = false;
@@ -87,6 +95,10 @@ int testStatus(int, char* [])
std::cerr << "Status Windows constructor does not produce Windows\n";
res = false;
}
+ if (status.IsSuccess()) {
+ std::cerr << "Status Windows gives true IsSuccess\n";
+ res = false;
+ }
if (status) {
std::cerr << "Status Windows kind is not false\n";
res = false;
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 39a19cbf2..6ccc7a7cb 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -436,7 +436,7 @@ static bool CheckFileOperations()
if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD)
#endif
{
- if (!symlinkStatus) {
+ if (!symlinkStatus.IsSuccess()) {
std::cerr << "CreateSymlink for: " << testBadSymlink << " -> "
<< testBadSymlinkTgt
<< " failed: " << symlinkStatus.GetString() << std::endl;
diff --git a/Templates/MSBuild/FlagTables/v143_Link.json b/Templates/MSBuild/FlagTables/v143_Link.json
index 4422f55bd..71d58f885 100644
--- a/Templates/MSBuild/FlagTables/v143_Link.json
+++ b/Templates/MSBuild/FlagTables/v143_Link.json
@@ -978,6 +978,13 @@
"flags": []
},
{
+ "name": "LinkControlFlowGuard",
+ "switch": "guard:cf",
+ "comment": "Control Flow Guard",
+ "value": "true",
+ "flags": []
+ },
+ {
"name": "LinkGuardEHContMetadata",
"switch": "guard:ehcont",
"comment": "Enable EH Continuation Metadata",
diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect
index 4870f658a..5e3cdb104 100644
--- a/Tests/CMakeLib/testRST.expect
+++ b/Tests/CMakeLib/testRST.expect
@@ -116,6 +116,12 @@ A literal block can be empty::
.. note::
Notes are called out.
+.. versionadded:: 1.2
+ Version blocks are preserved.
+
+.. versionchanged:: 2.3
+ Version blocks are preserved.
+
substituted text with multiple lines becomes one line
End of first include.
diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst
index 44931a756..413980183 100644
--- a/Tests/CMakeLib/testRST.rst
+++ b/Tests/CMakeLib/testRST.rst
@@ -123,6 +123,12 @@ A literal block can be empty::
.. note::
Notes are called out.
+.. versionadded:: 1.2
+ Version blocks are preserved.
+
+.. versionchanged:: 2.3
+ Version blocks are preserved.
+
.. |substitution| replace::
|nested substitution|
with multiple lines becomes one line
diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx
index 0607f449f..7d21959bf 100644
--- a/Tests/CMakeLib/testUVRAII.cxx
+++ b/Tests/CMakeLib/testUVRAII.cxx
@@ -169,7 +169,7 @@ static bool testAllMoves()
allTypes b(std::move(a));
allTypes c = std::move(b);
return true;
-};
+}
static bool testLoopReset()
{
@@ -192,7 +192,7 @@ static bool testLoopReset()
}
return true;
-};
+}
static bool testLoopDestructor()
{
@@ -217,7 +217,7 @@ static bool testLoopDestructor()
}
return true;
-};
+}
int testUVRAII(int, char** const)
{
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 341aba635..ecb54c7ae 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -39,6 +39,13 @@ set(ENV{HOME} \"${TEST_HOME}\")
")
endif()
+# Suppress generator deprecation warnings in test suite.
+if(CMAKE_GENERATOR MATCHES "^Visual Studio 10 2010")
+ set(TEST_WARN_VS10_CODE "set(ENV{CMAKE_WARN_VS10} OFF)")
+else()
+ set(TEST_WARN_VS10_CODE "")
+endif()
+
# 3.9 or later provides a definitive answer to whether we are multi-config
# through a global property. Prior to 3.9, CMAKE_CONFIGURATION_TYPES being set
# is assumed to mean multi-config, but developers might modify it so it is
@@ -250,6 +257,13 @@ if(BUILD_TESTING)
#---------------------------------------------------------------------------
# Add tests below here.
+ if(NOT DEFINED CMake_TEST_Qt6)
+ set(CMake_TEST_Qt6 1)
+ endif()
+ if(CMake_TEST_Qt6)
+ find_package(Qt6 COMPONENTS Core Widgets QUIET NO_MODULE)
+ endif()
+
if(NOT DEFINED CMake_TEST_Qt5)
set(CMake_TEST_Qt5 1)
endif()
@@ -1365,6 +1379,13 @@ if(BUILD_TESTING)
--test-command ${CMAKE_CTEST_COMMAND} -V
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment")
+ set_property(TEST Environment APPEND
+ PROPERTY ENVIRONMENT
+ "SET_FROM_AMBIENT_unset=base"
+ "SET_FROM_AMBIENT_replace=base"
+ "SET_FROM_AMBIENT_string=base"
+ "SET_FROM_AMBIENT_path=base"
+ "SET_FROM_AMBIENT_list=base")
add_test(QtAutomocNoQt ${CMAKE_CTEST_COMMAND}
--build-and-test
@@ -1377,6 +1398,9 @@ if(BUILD_TESTING)
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt")
+ if(CMake_TEST_Qt6 AND Qt6Widgets_FOUND)
+ add_subdirectory(Qt6Autogen)
+ endif()
if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
add_subdirectory(Qt5Autogen)
endif()
@@ -1442,12 +1466,14 @@ if(BUILD_TESTING)
GIF
Git
GLEW
+ GLUT
GnuTLS
GSL
GTK2
Iconv
ICU
Intl
+ Jasper
JPEG
JsonCpp
LAPACK
@@ -1543,6 +1569,8 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(FindMatlab.failure_reports ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
set(FindMatlab.r2018a_check_BUILD_OPTIONS ${FindMatlab_additional_test_options})
ADD_TEST_MACRO(FindMatlab.r2018a_check ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
+ set(FindMatlab.targets_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options})
+ ADD_TEST_MACRO(FindMatlab.targets_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>)
endif()
add_test(ExternalProject ${CMAKE_CTEST_COMMAND}
@@ -1640,6 +1668,55 @@ if(BUILD_TESTING)
WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
DEPENDS ExternalProjectUpdateSetup )
+ execute_process(
+ COMMAND ${CMAKE_COMMAND}
+ "-E" create_symlink
+ "${CMake_SOURCE_DIR}/Tests/CMakeLists.txt" # random source file that exists
+ "${CMake_BINARY_DIR}/Tests/try_to_create_symlink" # random target file in existing directory
+ RESULT_VARIABLE _symlink_result
+ OUTPUT_VARIABLE _symlink_stdout
+ ERROR_VARIABLE _symlink_stderr
+ )
+ if(_symlink_result EQUAL 0)
+ file(REMOVE "${CMake_BINARY_DIR}/Tests/try_to_create_symlink")
+ function(add_installmode_test _mode)
+ set(ENV{CMAKE_INSTALL_MODE} _mode)
+ set(_maybe_InstallMode_CTEST_OPTIONS)
+ set(_maybe_BUILD_OPTIONS)
+ if(_isMultiConfig)
+ set(_maybe_CTEST_OPTIONS -C $<CONFIGURATION>)
+ else()
+ set(_maybe_BUILD_OPTIONS "-DCMAKE_BUILD_TYPE=$<CONFIGURATION>")
+ endif()
+ add_test(
+ NAME "InstallMode-${_mode}"
+ COMMAND
+ ${CMAKE_CTEST_COMMAND} -V ${_maybe_CTEST_OPTIONS}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/InstallMode"
+ "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}"
+ ${build_generator_args}
+ --build-project superpro
+ --build-exe-dir "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}"
+ --force-new-ctest-process
+ --build-options
+ ${_maybe_BUILD_OPTIONS}
+ "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}/install"
+ )
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InstallMode-${_mode}")
+ unset(ENV{CMAKE_INSTALL_MODE})
+ endfunction()
+
+ add_installmode_test(COPY)
+ add_installmode_test(REL_SYMLINK)
+ add_installmode_test(REL_SYMLINK_OR_COPY)
+ add_installmode_test(ABS_SYMLINK)
+ add_installmode_test(ABS_SYMLINK_OR_COPY)
+ add_installmode_test(SYMLINK)
+ add_installmode_test(SYMLINK_OR_COPY)
+ endif()
+
+
# do each of the tutorial steps
function(add_tutorial_test step_name use_mymath tutorial_arg pass_regex)
set(tutorial_test_name Tutorial${step_name})
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index 52959e62e..9e0b89101 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -31,7 +31,6 @@ AddCMakeTest(CompilerIdVendor "")
AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
AddCMakeTest(PushCheckState "")
AddCMakeTest(While "")
-AddCMakeTest(CMakeHostSystemInformation "")
AddCMakeTest(FileDownload "")
set_tests_properties(CMake.FileDownload PROPERTIES
diff --git a/Tests/CPackNSISGenerator/CMakeLists.txt b/Tests/CPackNSISGenerator/CMakeLists.txt
index 64a8ef6a5..5d6320b8b 100644
--- a/Tests/CPackNSISGenerator/CMakeLists.txt
+++ b/Tests/CPackNSISGenerator/CMakeLists.txt
@@ -19,5 +19,6 @@ set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_MANIFEST_DPI_AWARE ON)
set(CPACK_NSIS_BRANDING_TEXT "CMake branding text")
set(CPACK_NSIS_BRANDING_TEXT_TRIM_POSITION "RIGHT")
+set(CPACK_NSIS_IGNORE_LICENSE_PAGE ON)
include(CPack)
diff --git a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
index 8bfcf26f5..31a2560e1 100644
--- a/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
+++ b/Tests/CPackNSISGenerator/RunCPackVerifyResult.cmake
@@ -60,3 +60,12 @@ if("${output_index}" EQUAL "-1")
else()
message(STATUS "Found BrandingText")
endif()
+
+# license page should not be present
+file(STRINGS "${project_file}" line REGEX "!insertmacro MUI_PAGE_LICENSE")
+string(FIND "${line}" "MUI_PAGE_LICENSE" output_index)
+if("${output_index}" EQUAL "-1")
+ message(STATUS "License not found in the project")
+else()
+ message(FATAL_ERROR "License found in the project")
+endif()
diff --git a/Tests/CTestTestSerialInDepends/test.ctest b/Tests/CTestTestSerialInDepends/test.ctest
index 28ee09436..cf0d314fb 100644
--- a/Tests/CTestTestSerialInDepends/test.ctest
+++ b/Tests/CTestTestSerialInDepends/test.ctest
@@ -2,6 +2,9 @@ set(CTEST_RUN_CURRENT_SCRIPT 0)
set(LOCK_FILE "${TEST_NAME}.lock")
+# Delete the old lock file in case it's lingering from a previous failed test run
+file(REMOVE "${LOCK_FILE}")
+
if("${TEST_NAME}" STREQUAL "i_want_to_be_alone")
file(GLOB LOCK_FILES *.lock)
if(LOCK_FILES)
diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt
index be5ccac50..669c412df 100644
--- a/Tests/Cuda/CMakeLists.txt
+++ b/Tests/Cuda/CMakeLists.txt
@@ -4,7 +4,6 @@ macro (add_cuda_test_macro name)
PROPERTY LABELS "CUDA")
endmacro ()
-add_cuda_test_macro(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures)
add_cuda_test_macro(Cuda.CXXStandardSetTwice CXXStandardSetTwice)
add_cuda_test_macro(Cuda.ObjectLibrary CudaObjectLibrary)
add_cuda_test_macro(Cuda.MixedStandardLevels1 MixedStandardLevels1)
diff --git a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt b/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt
deleted file mode 100644
index b01b9d7f0..000000000
--- a/Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-cmake_minimum_required(VERSION 3.18)
-project(ConsumeCompileFeatures CXX CUDA)
-#Goal for this example:
-
-#build a c++11 library that express a c++11 public compile feature
-#link a cuda library and verify it builds with c++11 enabled
-
-#build a standalone c++/cuda mixed executable where we express a c++11
-#compile feature.
-
-
-add_library(CudaConsumeLib STATIC static.cpp static.cu)
-target_compile_features(CudaConsumeLib PUBLIC cxx_nullptr)
-
-add_executable(CudaConsumeCompileFeatures main.cu)
-target_link_libraries(CudaConsumeCompileFeatures PRIVATE CudaConsumeLib)
diff --git a/Tests/Cuda/ConsumeCompileFeatures/main.cu b/Tests/Cuda/ConsumeCompileFeatures/main.cu
deleted file mode 100644
index bc3245013..000000000
--- a/Tests/Cuda/ConsumeCompileFeatures/main.cu
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#include <iostream>
-
-int static_cxx11_func(int);
-
-void test_functions()
-{
- auto x = static_cxx11_func(int(42));
- std::cout << x << std::endl;
-}
-
-int main(int argc, char** argv)
-{
- test_functions();
- std::cout
- << "this executable doesn't use cuda code, just call methods defined"
- << std::endl;
- std::cout << "in libraries that have cuda code" << std::endl;
- return 0;
-}
diff --git a/Tests/Cuda/ConsumeCompileFeatures/static.cpp b/Tests/Cuda/ConsumeCompileFeatures/static.cpp
deleted file mode 100644
index 565d52e10..000000000
--- a/Tests/Cuda/ConsumeCompileFeatures/static.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-#include <type_traits>
-
-int static_cuda11_func(int);
-
-int static_cxx11_func(int x)
-{
- return static_cuda11_func(x) + std::integral_constant<int, 32>::value;
-}
diff --git a/Tests/Cuda/ConsumeCompileFeatures/static.cu b/Tests/Cuda/ConsumeCompileFeatures/static.cu
deleted file mode 100644
index 73e43a865..000000000
--- a/Tests/Cuda/ConsumeCompileFeatures/static.cu
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include <type_traits>
-
-using tt = std::true_type;
-using ft = std::false_type;
-int __host__ static_cuda11_func(int x)
-{
- return x * x + std::integral_constant<int, 17>::value;
-}
diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in
index 7781ded84..7c6f76a24 100644
--- a/Tests/EnforceConfig.cmake.in
+++ b/Tests/EnforceConfig.cmake.in
@@ -36,3 +36,4 @@ unset(ENV{CMAKE_GENERATOR_TOOLSET})
unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS})
@TEST_HOME_ENV_CODE@
+@TEST_WARN_VS10_CODE@
diff --git a/Tests/Environment/CMakeLists.txt b/Tests/Environment/CMakeLists.txt
index 2b18d2466..abcf33c53 100644
--- a/Tests/Environment/CMakeLists.txt
+++ b/Tests/Environment/CMakeLists.txt
@@ -9,6 +9,7 @@ add_test(Environment1 Environment)
add_test(Environment2 Environment)
add_test(EchoEnvironment1 ${CMAKE_COMMAND} -E environment)
add_test(EchoEnvironment2 ${CMAKE_COMMAND} -E environment)
+add_test(EchoEnvironment3 ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_SOURCE_DIR}/check_mod.cmake")
# Make sure "CMAKE_ENV.*Happy Thanksgiving" is in the output of
# the "1" tests:
@@ -24,3 +25,79 @@ set_tests_properties(Environment1 EchoEnvironment1 PROPERTIES
set_tests_properties(Environment2 EchoEnvironment2 PROPERTIES
FAIL_REGULAR_EXPRESSION "CMAKE_ENV.*Happy Thanksgiving"
)
+
+set_property(TEST EchoEnvironment3
+ PROPERTY ENVIRONMENT
+ "SET_FROM_ENVIRONMENT_PROPERTY_unset=base"
+ "SET_FROM_ENVIRONMENT_PROPERTY_replace=base"
+ "SET_FROM_ENVIRONMENT_PROPERTY_string=base"
+ "SET_FROM_ENVIRONMENT_PROPERTY_path=base"
+ "SET_FROM_ENVIRONMENT_PROPERTY_list=base"
+)
+
+set_property(TEST EchoEnvironment3
+ PROPERTY ENVIRONMENT_MODIFICATION
+ # Modifying variables set in the ambient environment (see properties for
+ # this test in `Tests/CMakeLists.txt`).
+ "SET_FROM_AMBIENT_unset=unset:"
+ "SET_FROM_AMBIENT_replace=set:new"
+ "SET_FROM_AMBIENT_string=string_append:new"
+ "SET_FROM_AMBIENT_path=path_list_append:new"
+ "SET_FROM_AMBIENT_list=cmake_list_append:new"
+
+ # Modifying variables set in the `ENVIRONMENT` property.
+ "SET_FROM_ENVIRONMENT_PROPERTY_unset=unset:"
+ "SET_FROM_ENVIRONMENT_PROPERTY_replace=set:new"
+ "SET_FROM_ENVIRONMENT_PROPERTY_string=string_append:new"
+ "SET_FROM_ENVIRONMENT_PROPERTY_path=path_list_append:new"
+ "SET_FROM_ENVIRONMENT_PROPERTY_list=cmake_list_append:new"
+
+ # Variables expected to be unset.
+ "UNSET_EXPLICIT=set:value"
+ "UNSET_EXPLICIT=unset:"
+ "UNSET_VIA_RESET=set:value"
+ "UNSET_VIA_RESET=reset:"
+
+ # Direct settings.
+ "DIRECT=set:old"
+ "DIRECT=set:new"
+
+ # String manipulation.
+ "STRING_MANIP=set:-core-"
+ "STRING_MANIP=string_append:post-"
+ "STRING_MANIP=string_prepend:-pre"
+ "STRING_MANIP=string_append:suffix"
+ "STRING_MANIP=string_prepend:prefix"
+
+ # String manipulation on non-existent.
+ "STRING_DNE=string_append:post-"
+ "STRING_DNE=string_prepend:-pre"
+ "STRING_DNE=string_append:suffix"
+ "STRING_DNE=string_prepend:prefix"
+
+ # Path manipulation.
+ "PATH_MANIP=set:core"
+ "PATH_MANIP=path_list_append:post"
+ "PATH_MANIP=path_list_prepend:pre"
+ "PATH_MANIP=path_list_append:suffix"
+ "PATH_MANIP=path_list_prepend:prefix"
+
+ # Path manipulation on non-existent.
+ "PATH_DNE=path_list_append:post"
+ "PATH_DNE=path_list_prepend:pre"
+ "PATH_DNE=path_list_append:suffix"
+ "PATH_DNE=path_list_prepend:prefix"
+
+ # CMake list manipulation.
+ "CMAKE_LIST_MANIP=set:core"
+ "CMAKE_LIST_MANIP=cmake_list_append:post"
+ "CMAKE_LIST_MANIP=cmake_list_prepend:pre"
+ "CMAKE_LIST_MANIP=cmake_list_append:suffix"
+ "CMAKE_LIST_MANIP=cmake_list_prepend:prefix"
+
+ # CMake list manipulation on non-existent.
+ "CMAKE_LIST_DNE=cmake_list_append:post"
+ "CMAKE_LIST_DNE=cmake_list_prepend:pre"
+ "CMAKE_LIST_DNE=cmake_list_append:suffix"
+ "CMAKE_LIST_DNE=cmake_list_prepend:prefix"
+)
diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake
new file mode 100644
index 000000000..0f885f0f1
--- /dev/null
+++ b/Tests/Environment/check_mod.cmake
@@ -0,0 +1,79 @@
+execute_process(
+ COMMAND ${CMAKE_COMMAND} -E environment
+ OUTPUT_VARIABLE out
+ ERROR_VARIABLE err
+ RESULT_VARIABLE res)
+
+if (res)
+ message(FATAL_ERROR "Failed with exit code ${res}: ${err}")
+endif ()
+
+if (CMAKE_HOST_WIN32)
+ set(path_sep ";")
+else ()
+ set(path_sep ":")
+endif ()
+
+set(unexpect_SET_FROM_AMBIENT_unset "")
+set(unexpect_SET_FROM_ENVIRONMENT_PROPERTY_unset "")
+set(unexpect_UNSET_EXPLICIT "")
+set(unexpect_UNSET_VIA_RESET "")
+set(expect_DIRECT "new")
+set(expect_STRING_MANIP "prefix-pre-core-post-suffix")
+set(expect_PATH_MANIP "prefix${path_sep}pre${path_sep}core${path_sep}post${path_sep}suffix")
+set(expect_CMAKE_LIST_MANIP "prefix;pre;core;post;suffix")
+set(expect_STRING_DNE "prefix-prepost-suffix")
+set(expect_PATH_DNE "prefix${path_sep}pre${path_sep}post${path_sep}suffix")
+set(expect_CMAKE_LIST_DNE "prefix;pre;post;suffix")
+set(expect_SET_FROM_AMBIENT_replace "new")
+set(expect_SET_FROM_AMBIENT_string "basenew")
+set(expect_SET_FROM_AMBIENT_path "base${path_sep}new")
+set(expect_SET_FROM_AMBIENT_list "base;new")
+set(expect_SET_FROM_ENVIRONMENT_PROPERTY_replace "new")
+set(expect_SET_FROM_ENVIRONMENT_PROPERTY_string "basenew")
+set(expect_SET_FROM_ENVIRONMENT_PROPERTY_path "base${path_sep}new")
+set(expect_SET_FROM_ENVIRONMENT_PROPERTY_list "base;new")
+
+set(expected_vars
+ SET_FROM_AMBIENT_replace
+ SET_FROM_AMBIENT_string
+ SET_FROM_AMBIENT_path
+ SET_FROM_AMBIENT_list
+ SET_FROM_ENVIRONMENT_PROPERTY_replace
+ SET_FROM_ENVIRONMENT_PROPERTY_string
+ SET_FROM_ENVIRONMENT_PROPERTY_path
+ SET_FROM_ENVIRONMENT_PROPERTY_list
+ DIRECT
+ STRING_MANIP
+ PATH_MANIP
+ CMAKE_LIST_MANIP
+ STRING_DNE
+ PATH_DNE
+ CMAKE_LIST_DNE)
+
+while (out)
+ string(FIND "${out}" "\n" nl_pos)
+ string(SUBSTRING "${out}" 0 "${nl_pos}" line)
+ math(EXPR line_next "${nl_pos} + 1")
+ string(SUBSTRING "${out}" "${line_next}" -1 out)
+
+ string(FIND "${line}" "=" eq_pos)
+ string(SUBSTRING "${line}" 0 "${eq_pos}" name)
+ math(EXPR value_start "${eq_pos} + 1")
+ string(SUBSTRING "${line}" "${value_start}" -1 value)
+
+ if (DEFINED "unexpect_${name}")
+ message(SEND_ERROR "Found `${name}=${value}` when it should have been unset")
+ elseif (DEFINED "expect_${name}")
+ list(REMOVE_ITEM expected_vars "${name}")
+ if (expect_${name} STREQUAL value)
+ message(STATUS "Found `${name}=${value}` as expected")
+ else ()
+ message(SEND_ERROR "Found `${name}=${value}` when it should have been ${expect_${name}}")
+ endif ()
+ endif ()
+endwhile ()
+
+if (expected_vars)
+ message(SEND_ERROR "Did not test expected variables: ${expected_vars}")
+endif ()
diff --git a/Tests/FindBLAS/CMakeLists.txt b/Tests/FindBLAS/CMakeLists.txt
index 482cee876..00b254dfa 100644
--- a/Tests/FindBLAS/CMakeLists.txt
+++ b/Tests/FindBLAS/CMakeLists.txt
@@ -1,49 +1,2 @@
-foreach(variant IN LISTS CMake_TEST_FindBLAS)
- if(variant MATCHES "^([^.]+)\\.(.*)$")
- set(vendor "${CMAKE_MATCH_1}")
- set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
- else()
- set(vendor "${variant}")
- set(alt_compiler "")
- endif()
- if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_All)
- set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_All}")
- else()
- set(EXPECT_All "")
- endif()
- add_test(NAME FindBLAS.Test_${variant} COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test"
- "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}"
- ${build_generator_args}
- --build-project TestFindBLAS
- --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor}
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
-endforeach()
-
-foreach(variant IN LISTS CMake_TEST_FindBLAS_STATIC)
- if(variant MATCHES "^([^.]+)\\.(.*)$")
- set(vendor "${CMAKE_MATCH_1}")
- set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
- else()
- set(vendor "${variant}")
- set(alt_compiler "")
- endif()
- if(vendor STREQUAL "All" AND CMake_TEST_FindBLAS_STATIC_All)
- set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindBLAS_STATIC_All}")
- else()
- set(EXPECT_All "")
- endif()
- add_test(NAME FindBLAS.Test_${variant}_Static COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindBLAS/Test"
- "${CMake_BINARY_DIR}/Tests/FindBLAS/Test_${variant}_Static"
- ${build_generator_args}
- --build-project TestFindBLAS
- --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
-endforeach()
+include("${CMake_SOURCE_DIR}/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake")
+add_BLAS_LAPACK_tests(CMake_TEST_FindBLAS)
diff --git a/Tests/FindBLAS/Test/CMakeLists.txt b/Tests/FindBLAS/Test/CMakeLists.txt
index 73797496a..14bf19f39 100644
--- a/Tests/FindBLAS/Test/CMakeLists.txt
+++ b/Tests/FindBLAS/Test/CMakeLists.txt
@@ -4,12 +4,18 @@ include(CTest)
find_package(BLAS REQUIRED)
+if(NOT BLA_SIZEOF_INTEGER)
+ set(BLA_SIZEOF_INTEGER 4)
+endif()
+
add_executable(test_tgt main.c)
target_link_libraries(test_tgt BLAS::BLAS)
+target_compile_definitions(test_tgt PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER})
add_test(NAME test_tgt COMMAND test_tgt)
add_executable(test_var main.c)
target_link_libraries(test_var PRIVATE ${BLAS_LIBRARIES})
+target_compile_definitions(test_var PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER})
add_test(NAME test_var COMMAND test_var)
if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
@@ -17,4 +23,9 @@ if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64")
message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_lp64:\n ${BLAS_LIBRARIES}")
endif()
+elseif((BLA_VENDOR STREQUAL "Intel10_64ilp") OR
+ (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64ilp"))
+ if(NOT BLAS_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_ilp64")
+ message(FATAL_ERROR "BLAS_LIBRARIES does not start in mkl_intel_ilp64:\n ${BLAS_LIBRARIES}")
+ endif()
endif()
diff --git a/Tests/FindBLAS/Test/main.c b/Tests/FindBLAS/Test/main.c
index e61b02cbe..4fc9fe449 100644
--- a/Tests/FindBLAS/Test/main.c
+++ b/Tests/FindBLAS/Test/main.c
@@ -1,16 +1,25 @@
#include <assert.h>
+#include <stdint.h>
#include <string.h>
+#if BLA_SIZEOF_INTEGER == 4
+typedef int32_t blas_int;
+#elif BLA_SIZEOF_INTEGER == 8
+typedef int64_t blas_int;
+#else
+# error BLA_SIZEOF_INTEGER is not declared!
+#endif
+
// declare what parts of the blas C-API we need
-void dswap_(int* N, double* X, int* incX, double* Y, int* incY);
+void dswap_(blas_int* N, double* X, blas_int* incX, double* Y, blas_int* incY);
int main()
{
double x[4] = { 1, 2, 3, 4 };
double y[4] = { 8, 7, 7, 6 };
- int N = 4;
- int incX = 1;
- int incY = 1;
+ blas_int N = 4;
+ blas_int incX = 1;
+ blas_int incY = 1;
dswap_(&N, x, &incX, y, &incY);
return 0;
}
diff --git a/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake
new file mode 100644
index 000000000..42fe386f9
--- /dev/null
+++ b/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake
@@ -0,0 +1,53 @@
+function(add_BLAS_LAPACK_tests var)
+ if(var MATCHES "^CMake_TEST_Find(BLAS|LAPACK)$")
+ set(package "${CMAKE_MATCH_1}")
+ else()
+ message(FATAL_ERROR "Test list variable '${var}' not supported.")
+ endif()
+
+ set(all "")
+ set(compiler "")
+ set(model "")
+ set(static "")
+
+ set(sizeof_int_lp64 4)
+ set(sizeof_int_ilp64 8)
+
+ foreach(variant IN LISTS ${var})
+ if(variant MATCHES "^(all|compiler|model|static)=(.*)$")
+ set("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}")
+ continue()
+ elseif(variant MATCHES "^([^=]+)=(.*)$")
+ message(FATAL_ERROR "Unknown variable '${variant}'")
+ endif()
+ set(variant_name "${variant}")
+ set(variant_options "-DBLA_VENDOR=${variant}")
+ if(variant STREQUAL "All" AND all)
+ list(APPEND variant_options "-DEXPECT_All=${all}")
+ endif()
+ if(model)
+ if(NOT variant_name MATCHES "Intel10_64")
+ string(APPEND variant_name "_${model}")
+ endif()
+ list(APPEND variant_options "-DBLA_SIZEOF_INTEGER=${sizeof_int_${model}}")
+ endif()
+ if(compiler)
+ string(APPEND variant_name "_${compiler}")
+ list(APPEND variant_options "-DCMAKE_C_COMPILER=${compiler}")
+ endif()
+ if(static)
+ string(APPEND variant_name "_Static")
+ list(APPEND variant_options "-DBLA_STATIC=ON")
+ endif()
+ add_test(NAME Find${package}.Test_${variant_name} COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Find${package}/Test"
+ "${CMake_BINARY_DIR}/Tests/Find${package}/Test_${variant_name}"
+ ${build_generator_args}
+ --build-project TestFind${package}
+ --build-options ${build_options} ${variant_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+ endforeach()
+endfunction()
diff --git a/Tests/FindGLUT/CMakeLists.txt b/Tests/FindGLUT/CMakeLists.txt
new file mode 100644
index 000000000..e75ec408b
--- /dev/null
+++ b/Tests/FindGLUT/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_test(NAME FindGLUT.Test COMMAND ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindGLUT/Test"
+ "${CMake_BINARY_DIR}/Tests/FindGLUT/Test"
+ ${build_generator_args}
+ --build-project TestFindGLUT
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V
+ )
diff --git a/Tests/FindGLUT/Test/CMakeLists.txt b/Tests/FindGLUT/Test/CMakeLists.txt
new file mode 100644
index 000000000..0f4e53673
--- /dev/null
+++ b/Tests/FindGLUT/Test/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.21)
+project(TestFindGLUT C)
+include(CTest)
+
+find_package(GLUT REQUIRED)
+
+add_executable(testglut_tgt main.c)
+target_link_libraries(testglut_tgt GLUT::GLUT)
+add_test(NAME testglut_tgt COMMAND testglut_tgt)
+
+add_executable(testglut_var main.c)
+target_include_directories(testglut_var PRIVATE ${GLUT_INCLUDE_DIRS})
+target_link_libraries(testglut_var PRIVATE ${GLUT_LIBRARIES})
+add_test(NAME testglut_var COMMAND testglut_var)
+
+set_tests_properties(testglut_tgt testglut_var
+ PROPERTIES WILL_FAIL true)
diff --git a/Tests/FindGLUT/Test/main.c b/Tests/FindGLUT/Test/main.c
new file mode 100644
index 000000000..1c8569c12
--- /dev/null
+++ b/Tests/FindGLUT/Test/main.c
@@ -0,0 +1,11 @@
+#include <GL/glut.h>
+#include <stdio.h>
+
+int main()
+{
+ /* The following should call exit(1) and print
+ freeglut ERROR: Function <glutCreateWindow> called
+ without first calling 'glutInit'.
+ to stderr */
+ glutCreateWindow("gluttest");
+}
diff --git a/Tests/FindJasper/CMakeLists.txt b/Tests/FindJasper/CMakeLists.txt
new file mode 100644
index 000000000..1bfae78d2
--- /dev/null
+++ b/Tests/FindJasper/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindJasper.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindJasper/Test"
+ "${CMake_BINARY_DIR}/Tests/FindJasper/Test"
+ ${build_generator_args}
+ --build-project TestFindJasper
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindJasper/Test/CMakeLists.txt b/Tests/FindJasper/Test/CMakeLists.txt
new file mode 100644
index 000000000..1e9467d49
--- /dev/null
+++ b/Tests/FindJasper/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.21)
+project(TestFindJasper C)
+include(CTest)
+
+find_package(Jasper)
+
+add_definitions(-DCMAKE_EXPECTED_JASPER_VERSION=${JASPER_VERSION_STRING})
+
+add_executable(test_jasper_tgt main.c)
+target_link_libraries(test_jasper_tgt Jasper::Jasper)
+add_test(NAME test_jasper_tgt COMMAND test_jasper_tgt)
+
+add_executable(test_jasper_var main.c)
+target_include_directories(test_jasper_var PRIVATE ${JASPER_INCLUDE_DIRS})
+target_link_libraries(test_jasper_var PRIVATE ${JASPER_LIBRARIES})
+add_test(NAME test_jasper_var COMMAND test_jasper_var)
diff --git a/Tests/FindJasper/Test/main.c b/Tests/FindJasper/Test/main.c
new file mode 100644
index 000000000..771344dea
--- /dev/null
+++ b/Tests/FindJasper/Test/main.c
@@ -0,0 +1,17 @@
+#include <assert.h>
+// clang-format off
+#include <stdio.h>
+#include <jasper/jasper.h>
+// clang-format on
+
+int main()
+{
+ /* Without any JPEG file to open, test that the call fails as
+ expected. This tests that linking worked. */
+ jas_init();
+ jas_image_t* img = jas_image_create0();
+ jas_image_destroy(img);
+ jas_cleanup();
+
+ return (JAS_VERSION != CMAKE_EXPECTED_JASPER_VERSION);
+}
diff --git a/Tests/FindLAPACK/CMakeLists.txt b/Tests/FindLAPACK/CMakeLists.txt
index 535c7b60e..a2470ef14 100644
--- a/Tests/FindLAPACK/CMakeLists.txt
+++ b/Tests/FindLAPACK/CMakeLists.txt
@@ -1,49 +1,2 @@
-foreach(variant IN LISTS CMake_TEST_FindLAPACK)
- if(variant MATCHES "^([^.]+)\\.(.*)$")
- set(vendor "${CMAKE_MATCH_1}")
- set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
- else()
- set(vendor "${variant}")
- set(alt_compiler "")
- endif()
- if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_All)
- set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_All}")
- else()
- set(EXPECT_All "")
- endif()
- add_test(NAME FindLAPACK.Test_${variant} COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test"
- "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}"
- ${build_generator_args}
- --build-project TestFindLAPACK
- --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor}
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
-endforeach()
-
-foreach(variant IN LISTS CMake_TEST_FindLAPACK_STATIC)
- if(variant MATCHES "^([^.]+)\\.(.*)$")
- set(vendor "${CMAKE_MATCH_1}")
- set(alt_compiler "-DCMAKE_C_COMPILER=${CMAKE_MATCH_2}")
- else()
- set(vendor "${variant}")
- set(alt_compiler "")
- endif()
- if(vendor STREQUAL "All" AND CMake_TEST_FindLAPACK_STATIC_All)
- set(EXPECT_All "-DEXPECT_All=${CMake_TEST_FindLAPACK_STATIC_All}")
- else()
- set(EXPECT_All "")
- endif()
- add_test(NAME FindLAPACK.Test_${variant}_Static COMMAND
- ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/FindLAPACK/Test"
- "${CMake_BINARY_DIR}/Tests/FindLAPACK/Test_${variant}_Static"
- ${build_generator_args}
- --build-project TestFindLAPACK
- --build-options ${build_options} ${alt_compiler} ${EXPECT_All} -DBLA_VENDOR=${vendor} -DBLA_STATIC=ON
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
- )
-endforeach()
+include("${CMake_SOURCE_DIR}/Tests/FindBLAS/add_BLAS_LAPACK_tests.cmake")
+add_BLAS_LAPACK_tests(CMake_TEST_FindLAPACK)
diff --git a/Tests/FindLAPACK/Test/CMakeLists.txt b/Tests/FindLAPACK/Test/CMakeLists.txt
index 23a43acec..f5d5a7391 100644
--- a/Tests/FindLAPACK/Test/CMakeLists.txt
+++ b/Tests/FindLAPACK/Test/CMakeLists.txt
@@ -4,12 +4,18 @@ include(CTest)
find_package(LAPACK REQUIRED)
+if(NOT BLA_SIZEOF_INTEGER)
+ set(BLA_SIZEOF_INTEGER 4)
+endif()
+
add_executable(test_tgt main.c)
target_link_libraries(test_tgt LAPACK::LAPACK)
+target_compile_definitions(test_tgt PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER})
add_test(NAME test_tgt COMMAND test_tgt)
add_executable(test_var main.c)
target_link_libraries(test_var PRIVATE ${LAPACK_LIBRARIES})
+target_compile_definitions(test_var PUBLIC BLA_SIZEOF_INTEGER=${BLA_SIZEOF_INTEGER})
add_test(NAME test_var COMMAND test_var)
if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
@@ -17,4 +23,9 @@ if((BLA_VENDOR STREQUAL "Intel10_64lp") OR
if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_lp64")
message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_lp64:\n ${LAPACK_LIBRARIES}")
endif()
+elseif((BLA_VENDOR STREQUAL "Intel10_64ilp") OR
+ (BLA_VENDOR STREQUAL "All" AND EXPECT_All STREQUAL "Intel10_64ilp"))
+ if(NOT LAPACK_LIBRARIES MATCHES "^(-Wl,--start-group;)?[^;]*mkl_intel_ilp64")
+ message(FATAL_ERROR "LAPACK_LIBRARIES does not start in mkl_intel_ilp64:\n ${LAPACK_LIBRARIES}")
+ endif()
endif()
diff --git a/Tests/FindLAPACK/Test/main.c b/Tests/FindLAPACK/Test/main.c
index 5873e7b47..dd33fb39a 100644
--- a/Tests/FindLAPACK/Test/main.c
+++ b/Tests/FindLAPACK/Test/main.c
@@ -1,8 +1,18 @@
#include <assert.h>
+#include <stdint.h>
#include <string.h>
+#if BLA_SIZEOF_INTEGER == 4
+typedef int32_t blas_int;
+#elif BLA_SIZEOF_INTEGER == 8
+typedef int64_t blas_int;
+#else
+# error BLA_SIZEOF_INTEGER is not declared!
+#endif
+
// declare what parts of the lapack C-API we need
-void dgesv_(int*, int*, double*, int*, int*, double*, int*, int*);
+void dgesv_(blas_int*, blas_int*, double*, blas_int*, blas_int*, double*,
+ blas_int*, blas_int*);
int main()
{
@@ -10,11 +20,11 @@ int main()
0, 1, 2, 3, 4, 5, 6, 7,
};
double B[2] = { 0, 5 };
- int ipiv[2] = { 0, 0 };
- int info = 0;
+ blas_int ipiv[2] = { 0, 0 };
+ blas_int info = 0;
- int dim = 2;
- int numCols = 1;
+ blas_int dim = 2;
+ blas_int numCols = 1;
dgesv_(&dim, &numCols, A, &dim, ipiv, B, &dim, &info);
return 0;
}
diff --git a/Tests/FindMatlab/targets_checks/CMakeLists.txt b/Tests/FindMatlab/targets_checks/CMakeLists.txt
new file mode 100644
index 000000000..4af7cc360
--- /dev/null
+++ b/Tests/FindMatlab/targets_checks/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required (VERSION 2.8.12)
+enable_testing()
+project(targets_checks)
+
+set(MATLAB_FIND_DEBUG TRUE)
+
+if(NOT "${MCR_ROOT}" STREQUAL "")
+ set(Matlab_ROOT_DIR "${MCR_ROOT}")
+ if(NOT EXISTS "${MCR_ROOT}")
+ message(FATAL_ERROR "MCR does not exist ${MCR_ROOT}")
+ endif()
+endif()
+
+# the success of the following command is dependent on the current configuration:
+# - on 32bits builds (cmake is building with 32 bits), it looks for 32 bits Matlab
+# - on 64bits builds (cmake is building with 64 bits), it looks for 64 bits Matlab
+find_package(Matlab REQUIRED COMPONENTS ENG_LIBRARY MAT_LIBRARY
+ OPTIONAL_COMPONENTS MAIN_PROGRAM)
+
+if(NOT TARGET Matlab::mx)
+ message(FATAL_ERROR "Matlab::mx target does not exist")
+endif()
+
+if(NOT TARGET Matlab::mex)
+ message(FATAL_ERROR "Matlab::mex target does not exist")
+endif()
+
+if(NOT TARGET Matlab::eng)
+ message(FATAL_ERROR "Matlab::eng target does not exist")
+endif()
+
+if(NOT TARGET Matlab::mat)
+ message(FATAL_ERROR "Matlab::mat target does not exist")
+endif()
+
+matlab_add_mex(
+ # target name
+ NAME cmake_matlab_test_wrapper1
+ # output name
+ OUTPUT_NAME cmake_matlab_mex1
+ SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp
+ DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt
+ LINK_TO Matlab::mex
+ )
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index d4c19c79b..f00565e56 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -2,17 +2,26 @@ cmake_minimum_required (VERSION 2.6)
project(IncludeDirectories)
if (((CMAKE_C_COMPILER_ID STREQUAL GNU AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 4.4)
- OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR CMAKE_C_COMPILER_ID STREQUAL AppleClang)
+ OR (CMAKE_C_COMPILER_ID STREQUAL Clang AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+ OR CMAKE_C_COMPILER_ID STREQUAL NVHPC
+ OR CMAKE_C_COMPILER_ID STREQUAL AppleClang
+ OR ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC" AND
+ CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "19.29.30036.3" AND
+ NOT CMAKE_GENERATOR MATCHES "Visual Studio")) # No support for VS generators yet.
AND (CMAKE_GENERATOR STREQUAL "Unix Makefiles"
OR CMAKE_GENERATOR STREQUAL "Ninja"
OR (CMAKE_GENERATOR STREQUAL "Xcode" AND NOT XCODE_VERSION VERSION_LESS 6.0)))
- include(CheckCXXCompilerFlag)
- check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test)
- if(run_sys_includes_test)
- # The Bullseye wrapper appears to break the -isystem effect.
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out)
- if("x${out}" MATCHES "Bullseye")
- set(run_sys_includes_test 0)
+ if ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC")
+ set(run_sys_includes_test 1)
+ else ()
+ include(CheckCXXCompilerFlag)
+ check_cxx_compiler_flag(-Wunused-variable run_sys_includes_test)
+ if(run_sys_includes_test)
+ # The Bullseye wrapper appears to break the -isystem effect.
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE out ERROR_VARIABLE out)
+ if("x${out}" MATCHES "Bullseye")
+ set(run_sys_includes_test 0)
+ endif()
endif()
endif()
if (run_sys_includes_test)
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
index dee39c826..a746a681b 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/CMakeLists.txt
@@ -6,9 +6,17 @@ project(SystemIncludeDirectories)
add_library(systemlib systemlib.cpp)
target_include_directories(systemlib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/systemlib")
+function (apply_error_flags target)
+ if (MSVC)
+ target_compile_options(${target} PRIVATE /we4101)
+ else ()
+ target_compile_options(${target} PRIVATE -Werror=unused-variable)
+ endif ()
+endfunction ()
+
add_library(upstream upstream.cpp)
target_link_libraries(upstream LINK_PUBLIC systemlib)
-target_compile_options(upstream PRIVATE -Werror=unused-variable)
+apply_error_flags(upstream)
target_include_directories(upstream SYSTEM PUBLIC
$<TARGET_PROPERTY:systemlib,INTERFACE_INCLUDE_DIRECTORIES>
@@ -29,7 +37,7 @@ endif()
add_library(consumer consumer.cpp)
target_link_libraries(consumer upstream config_specific)
-target_compile_options(consumer PRIVATE -Werror=unused-variable)
+apply_error_flags(consumer)
add_library(iface IMPORTED INTERFACE)
set_property(TARGET iface PROPERTY INTERFACE_INCLUDE_DIRECTORIES
@@ -38,21 +46,21 @@ set_property(TARGET iface PROPERTY INTERFACE_INCLUDE_DIRECTORIES
add_library(imported_consumer imported_consumer.cpp)
target_link_libraries(imported_consumer iface)
-target_compile_options(imported_consumer PRIVATE -Werror=unused-variable)
+apply_error_flags(imported_consumer)
add_library(imported_consumer2 imported_consumer.cpp)
target_link_libraries(imported_consumer2 imported_consumer)
-target_compile_options(imported_consumer2 PRIVATE -Werror=unused-variable)
+apply_error_flags(imported_consumer2)
# add a target which has a relative system include
add_library(somelib imported_consumer.cpp)
target_include_directories(somelib SYSTEM PUBLIC "systemlib_header_only")
-target_compile_options(somelib PRIVATE -Werror=unused-variable)
+apply_error_flags(somelib)
# add a target which consumes a relative system include
add_library(otherlib upstream.cpp)
target_link_libraries(otherlib PUBLIC somelib)
-target_compile_options(somelib PRIVATE -Werror=unused-variable)
+apply_error_flags(otherlib)
macro(do_try_compile error_option)
set(TC_ARGS
@@ -61,7 +69,11 @@ macro(do_try_compile error_option)
LINK_LIBRARIES iface
)
if (${error_option} STREQUAL WITH_ERROR)
- list(APPEND TC_ARGS COMPILE_DEFINITIONS -Werror=unused-variable)
+ if (MSVC)
+ list(APPEND TC_ARGS COMPILE_DEFINITIONS /we4101)
+ else ()
+ list(APPEND TC_ARGS COMPILE_DEFINITIONS -Werror=unused-variable)
+ endif ()
endif()
try_compile(${TC_ARGS})
endmacro()
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp
index a13f08fdc..3da308d5d 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/consumer.cpp
@@ -1,5 +1,6 @@
-#include "config_iface.h"
+#include <config_iface.h>
+
#include "upstream.h"
int consumer()
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp b/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp
index 1dbe819e1..53759b11c 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/imported_consumer.cpp
@@ -1,5 +1,5 @@
-#include "systemlib.h"
+#include <systemlib.h>
int main()
{
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h
index a670c2a48..3daf69eb6 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h
+++ b/Tests/IncludeDirectories/SystemIncludeDirectories/upstream.h
@@ -2,7 +2,7 @@
#ifndef UPSTREAM_H
#define UPSTREAM_H
-#include "systemlib.h"
+#include <systemlib.h>
#ifdef _WIN32
__declspec(dllexport)
diff --git a/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt b/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt
index 70dfa017b..5d58633e5 100644
--- a/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt
+++ b/Tests/IncludeDirectories/SystemIncludeDirectoriesPerLang/CMakeLists.txt
@@ -7,14 +7,14 @@ set_target_properties(c_interface PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "$<$<COMPILE_LANGUAGE:C>:${CMAKE_CURRENT_SOURCE_DIR}>"
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "$<$<COMPILE_LANGUAGE:C>:${CMAKE_CURRENT_SOURCE_DIR}>"
)
-target_compile_options(c_interface INTERFACE "$<$<COMPILE_LANG_AND_ID:C,GNU,Clang>:-Werror=unused-variable>")
+target_compile_options(c_interface INTERFACE "$<$<COMPILE_LANG_AND_ID:C,GNU,Clang>:-Werror=unused-variable>;$<$<COMPILE_LANG_AND_ID:C,MSVC>:/we4101>")
add_library(cxx_interface INTERFACE)
set_target_properties(cxx_interface PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/cxx_system_include>"
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_CURRENT_SOURCE_DIR}/cxx_system_include>"
)
-target_compile_options(cxx_interface INTERFACE "$<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang>:-Werror=unused-variable>")
+target_compile_options(cxx_interface INTERFACE "$<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang>:-Werror=unused-variable>;$<$<COMPILE_LANG_AND_ID:C,MSVC>:/we4101>")
# The C header must come before the C++ header for this test to smoke out the
# failure. The order of sources is how CMake determines the include cache
diff --git a/Tests/InstallMode/CMakeLists.txt b/Tests/InstallMode/CMakeLists.txt
new file mode 100644
index 000000000..96c83a05d
--- /dev/null
+++ b/Tests/InstallMode/CMakeLists.txt
@@ -0,0 +1,124 @@
+cmake_minimum_required(VERSION 3.20.0)
+
+project(superpro LANGUAGES NONE)
+
+add_subdirectory(superpro)
+
+include(Subproject.cmake)
+add_subproject(static_lib DIR subpro_a_static_lib)
+add_subproject(shared_lib DIR subpro_b_shared_lib)
+add_subproject(nested_lib DIR subpro_c_nested_lib NO_INSTALL)
+add_subproject(executable DIR subpro_d_executable
+ DEPENDS
+ static_lib
+ shared_lib
+ nested_lib
+)
+
+include(CTest)
+if(BUILD_TESTING)
+ enable_language(CXX) # required by GNUInstallDirs
+ include(GNUInstallDirs)
+
+ macro(testme _name _path _symlink)
+ add_test(
+ NAME "${_name}"
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-DFILE_PATH=${CMAKE_INSTALL_PREFIX}/${_path}"
+ "-DEXPECT_SYMLINK:BOOL=${_symlink}"
+ "-DEXPECT_ABSOLUTE:BOOL=${ARGN}"
+ "-P" "${CMAKE_SOURCE_DIR}/Test.cmake"
+ )
+ endmacro()
+
+ set(_mode $ENV{CMAKE_INSTALL_MODE})
+ if(NOT "${_mode}" OR "${_mode}" STREQUAL "COPY")
+ set(expect_symlink NO)
+ elseif("${_mode}" MATCHES "(REL_)?SYMLINK(_OR_COPY)?")
+ set(expect_symlink YES)
+ set(expect_absolute NO)
+ elseif("${_mode}" MATCHES "ABS_SYMLINK(_OR_COPY)?")
+ set(expect_symlink YES)
+ set(expect_absolute YES)
+ endif()
+
+ # toplevel project should respect CMAKE_INSTALL_MODE
+
+ testme(superproj_file_copy
+ "file_copy.txt" NO)
+ testme(superproj_file_copy_file
+ "file_copy_file.txt" NO)
+ testme(superproj_file_install
+ "file_install.txt"
+ ${expect_symlink}
+ ${expect_absolute})
+ testme(superproj_file_create_link_symbolic
+ "file_create_link_symbolic.txt" YES YES)
+
+ # subprojects should receive and respect CMAKE_INSTALL_MODE too
+
+ testme(subpro_a_static_lib_header
+ "${CMAKE_INSTALL_INCLUDEDIR}/static_lib.h"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+ testme(subpro_a_static_lib_libfile
+ "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_static_lib${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+
+ testme(subpro_b_shared_lib_header
+ "${CMAKE_INSTALL_INCLUDEDIR}/shared_lib.h"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+
+ if(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG AND
+ "${CMAKE_CXX_CREATE_SHARED_MODULE}" MATCHES "SONAME_FLAG")
+ # due to semver, this is always a link
+ testme(subpro_b_shared_lib_libfile
+ "${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}the_shared_lib${CMAKE_SHARED_LIBRARY_SUFFIX}"
+ YES
+ ${expect_absolute}
+ )
+ # this is the actual shared lib, so should follow CMAKE_INSTALL_MODE rules
+ testme(subpro_b_shared_lib_libfile_versuffix
+ "${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}the_shared_lib${CMAKE_SHARED_LIBRARY_SUFFIX}.2.3.4"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+ endif()
+
+ testme(subpro_d_executable_exefile
+ "${CMAKE_INSTALL_BINDIR}/the_executable${CMAKE_EXECUTABLE_SUFFIX}"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+
+ # nested subprojects should receive and respect CMAKE_INSTALL_MODE too
+
+ testme(subsubpro_c1_header
+ "${CMAKE_INSTALL_INCLUDEDIR}/c1_lib.h"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+ testme(subsubpro_c1_libfile
+ "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_c1_lib${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+
+ testme(subsubpro_c2_header
+ "${CMAKE_INSTALL_INCLUDEDIR}/c2_lib.h"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+ testme(subsubpro_c2_libfile
+ "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}the_c2_lib${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ ${expect_symlink}
+ ${expect_absolute}
+ )
+endif()
diff --git a/Tests/InstallMode/README.txt b/Tests/InstallMode/README.txt
new file mode 100644
index 000000000..a4316ebb5
--- /dev/null
+++ b/Tests/InstallMode/README.txt
@@ -0,0 +1,43 @@
+This is an example superbuild project to demonstrate the use of the
+CMAKE_INSTALL_MODE environment variable on.
+
+The project hierarchy is like (B = Builds / D = Link Dependency):
+
++---------------------------------------------------------------------+
+| Superbuild (Top) |
++---------------------------------------------------------------------+
+ | | | |
+ | | | |
+ (B) (B) (B) (B)
+ | | | |
+ v v v v
++---------------+ +---------------+ +---------------+ +---------------+
+| A: Static Lib | | B: Shared Lib | | C: Nested | | D: Executable |
+| Project | | Project | | Superbuild | | Project |
++---------------+ +---------------+ +---------------+ +---------------+
+ ^ ^ | | | | |
+ | | (B) (B) | | |
+ | | | | | | |
+ | | v | | | |
+ | | +----------------+ | | | |
+ | | | C1: Static Lib | | | | |
+ | | | Project | | (D) (D) (D)
+ | | +----------------+ | | | |
+ | | ^ | | | |
+ | | | v | | |
+ | | (D) +----------------+ | | |
+ | | | | C2: Static Lib |<---+ | |
+ | | +--| Project | | |
+ | | +----------------+ | |
+ | | | |
+ | +------------------------------------+ |
+ | |
+ +--------------------------------------------------------+
+
+The superbuild system is built on top of ExternalProject_Add().
+
+NOTE that the subprojects will configure, build and install
+during the build phase ('make') of the top-level project.
+There is no install target in the top-level project!
+The CMAKE_INSTALL_PREFIX is therefore populated during the build
+phase already.
diff --git a/Tests/InstallMode/Subproject.cmake b/Tests/InstallMode/Subproject.cmake
new file mode 100644
index 000000000..826e61e02
--- /dev/null
+++ b/Tests/InstallMode/Subproject.cmake
@@ -0,0 +1,73 @@
+include(ExternalProject)
+
+# add_subproject(<name> [NO_INSTALL] [DIR <dirname>] [DEPENDS [subpro_dep ...]])
+function(add_subproject _name)
+ cmake_parse_arguments(_arg "NO_INSTALL" "DIR" "DEPENDS" ${ARGN})
+
+ if(_arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "There are unparsed arguments")
+ endif()
+
+ set(_maybe_NO_INSTALL)
+ if(_arg_NO_INSTALL)
+ set(_maybe_NO_INSTALL INSTALL_COMMAND "")
+ endif()
+
+ if(CMAKE_GENERATOR MATCHES "Ninja Multi-Config")
+ # Replace list separator before passing on to ExternalProject_Add
+ string(REPLACE ";" "|" _CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}")
+ string(REPLACE ";" "|" _CROSS_CONFIGS "${CMAKE_CROSS_CONFIGS}")
+ string(REPLACE ";" "|" _DEFAULT_CONFIGS "${CMAKE_DEFAULT_CONFIGS}")
+
+ set(_maybe_NINJA_MULTICONFIG_ARGS
+ "-DCMAKE_CONFIGURATION_TYPES:STRINGS=${_CONFIGURATION_TYPES}"
+ "-DCMAKE_CROSS_CONFIGS:STRINGS=${_CROSS_CONFIGS}"
+ "-DCMAKE_DEFAULT_BUILD_TYPE:STRING=${CMAKE_DEFAULT_BUILD_TYPE}"
+ "-DCMAKE_DEFAULT_CONFIGS:STRINGS=${_DEFAULT_CONFIGS}"
+ )
+ endif()
+
+ ExternalProject_Add("${_name}"
+ DOWNLOAD_COMMAND ""
+ UPDATE_COMMAND ""
+ UPDATE_DISCONNECTED ON
+
+ "${_maybe_NO_INSTALL}"
+
+ BUILD_ALWAYS ON
+
+ LOG_DOWNLOAD OFF
+ LOG_UPDATE OFF
+ LOG_PATCH OFF
+ LOG_CONFIGURE OFF
+ LOG_BUILD OFF
+ LOG_INSTALL OFF
+
+ SOURCE_DIR "${PROJECT_SOURCE_DIR}/${_arg_DIR}"
+
+ # Private build directory per subproject
+ BINARY_DIR "${PROJECT_BINARY_DIR}/subproject/${_arg_DIR}"
+
+ # Common install directory, populated immediately
+ # during build (during build - not install - of superproject)
+ INSTALL_DIR "${CMAKE_INSTALL_PREFIX}"
+
+ DEPENDS
+ ${_arg_DEPENDS}
+
+ LIST_SEPARATOR "|"
+ CMAKE_ARGS
+ "-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>"
+
+ # We can rely on ExternalProject to pick the right
+ # generator (and architecture/toolset where applicable),
+ # however, we need to explicitly inherit other parent
+ # project's build settings.
+ "-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+ "${_maybe_NINJA_MULTICONFIG_ARGS}"
+
+ # Subproject progress reports clutter up the output, disable
+ "-DCMAKE_TARGET_MESSAGES:BOOL=OFF"
+ "-DCMAKE_RULE_MESSAGES:BOOL=OFF"
+ )
+endfunction()
diff --git a/Tests/InstallMode/Test.cmake b/Tests/InstallMode/Test.cmake
new file mode 100644
index 000000000..46c8fa1da
--- /dev/null
+++ b/Tests/InstallMode/Test.cmake
@@ -0,0 +1,38 @@
+message("Testing...")
+message("FILE_PATH = ${FILE_PATH}")
+message("EXPECT_SYMLINK = ${EXPECT_SYMLINK}")
+message("EXPECT_ABSOLUTE = ${EXPECT_ABSOLUTE}")
+
+if(NOT DEFINED FILE_PATH)
+ message(FATAL_ERROR "FILE_PATH variable must be defined")
+endif()
+
+if(NOT EXISTS "${FILE_PATH}")
+ message(FATAL_ERROR "File ${FILE_PATH} does not exist")
+endif()
+
+if(NOT DEFINED EXPECT_SYMLINK)
+ message(FATAL_ERROR "EXPECT_SYMLINK must be defined")
+endif()
+
+if(EXPECT_SYMLINK)
+ if(NOT DEFINED EXPECT_ABSOLUTE)
+ message(FATAL_ERROR "EXPECT_ABSOLUTE variable must be defined")
+ endif()
+
+ if(NOT IS_SYMLINK "${FILE_PATH}")
+ message(FATAL_ERROR "${FILE_PATH} must be a symlink")
+ endif()
+
+ file(READ_SYMLINK "${FILE_PATH}" TARGET_PATH)
+
+ if(EXPECT_ABSOLUTE AND NOT IS_ABSOLUTE "${TARGET_PATH}")
+ message(FATAL_ERROR "${FILE_PATH} must be an absolute symlink")
+ elseif(NOT EXPECT_ABSOLUTE AND IS_ABSOLUTE "${TARGET_PATH}")
+ message(FATAL_ERROR "${FILE_PATH} must be a relative symlink")
+ endif()
+else()
+ if(IS_SYMLINK "${FILE_PATH}")
+ message(FATAL_ERROR "${FILE_PATH} must NOT be a symlink")
+ endif()
+endif()
diff --git a/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt b/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt
new file mode 100644
index 000000000..7cd32cc6e
--- /dev/null
+++ b/Tests/InstallMode/subpro_a_static_lib/CMakeLists.txt
@@ -0,0 +1,60 @@
+# This CMakeLists.txt is part of the subproject A (ExternalProject_Add).
+
+cmake_minimum_required(VERSION 3.20)
+project(static_lib_project VERSION 1.2.3 LANGUAGES CXX)
+
+include(GNUInstallDirs)
+
+add_library(the_static_lib STATIC
+ "include/static_lib.h"
+ "src/static_lib.cpp"
+)
+
+target_include_directories(the_static_lib PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+)
+
+install(
+ TARGETS
+ the_static_lib
+ EXPORT main
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+)
+
+set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
+
+include(CMakePackageConfigHelpers)
+
+configure_package_config_file(
+ "cmake/PackageConfig.cmake.in"
+ "${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}"
+ PATH_VARS
+ CMAKE_INSTALL_INCLUDEDIR
+ CMAKE_INSTALL_LIBDIR
+)
+
+write_basic_package_version_file("${PROJECT_NAME}Version.cmake"
+ VERSION "${PROJECT_VERSION}"
+ COMPATIBILITY SameMajorVersion
+)
+
+install(
+ EXPORT main
+ FILE "${PROJECT_NAME}Targets.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
+
+install(
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
diff --git a/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in
new file mode 100644
index 000000000..0fe72c91f
--- /dev/null
+++ b/Tests/InstallMode/subpro_a_static_lib/cmake/PackageConfig.cmake.in
@@ -0,0 +1,8 @@
+set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
+
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+
+set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
+set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
diff --git a/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h b/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h
new file mode 100644
index 000000000..bd82d2eea
--- /dev/null
+++ b/Tests/InstallMode/subpro_a_static_lib/include/static_lib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void static_hello();
diff --git a/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp b/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp
new file mode 100644
index 000000000..fe1cd854a
--- /dev/null
+++ b/Tests/InstallMode/subpro_a_static_lib/src/static_lib.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+
+#include <static_lib.h>
+
+using namespace std;
+
+void static_hello()
+{
+ cout << "Hello from static_lib" << endl;
+}
diff --git a/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt
new file mode 100644
index 000000000..b3d9cb2fe
--- /dev/null
+++ b/Tests/InstallMode/subpro_b_shared_lib/CMakeLists.txt
@@ -0,0 +1,75 @@
+# This CMakeLists.txt is part of the subproject B (ExternalProject_Add).
+
+cmake_minimum_required(VERSION 3.20)
+project(shared_lib_project VERSION 2.3.4 LANGUAGES CXX)
+
+include(GNUInstallDirs)
+include(GenerateExportHeader)
+
+add_library(the_shared_lib SHARED
+ "include/shared_lib.h"
+ "src/shared_lib.cpp"
+)
+
+generate_export_header(the_shared_lib
+ BASE_NAME shared_lib
+ EXPORT_FILE_NAME include/shared_lib_export.h
+)
+
+set_target_properties(the_shared_lib
+ PROPERTIES
+ VERSION "${PROJECT_VERSION}"
+ SOVERSION "${PROJECT_VERSION}"
+)
+
+target_include_directories(the_shared_lib PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+install(
+ DIRECTORY
+ "${CMAKE_CURRENT_SOURCE_DIR}/include/"
+ "${CMAKE_CURRENT_BINARY_DIR}/include/"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+)
+
+install(
+ TARGETS
+ the_shared_lib
+ EXPORT main
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+)
+
+set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
+
+include(CMakePackageConfigHelpers)
+
+configure_package_config_file(
+ "cmake/PackageConfig.cmake.in"
+ "${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}"
+ PATH_VARS
+ CMAKE_INSTALL_INCLUDEDIR
+ CMAKE_INSTALL_LIBDIR
+)
+
+write_basic_package_version_file("${PROJECT_NAME}Version.cmake"
+ VERSION "${PROJECT_VERSION}"
+ COMPATIBILITY SameMajorVersion
+)
+
+install(
+ EXPORT main
+ FILE "${PROJECT_NAME}Targets.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
+
+install(
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
diff --git a/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in
new file mode 100644
index 000000000..0fe72c91f
--- /dev/null
+++ b/Tests/InstallMode/subpro_b_shared_lib/cmake/PackageConfig.cmake.in
@@ -0,0 +1,8 @@
+set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
+
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+
+set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
+set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
diff --git a/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h
new file mode 100644
index 000000000..550b2b44d
--- /dev/null
+++ b/Tests/InstallMode/subpro_b_shared_lib/include/shared_lib.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <shared_lib_export.h>
+
+void SHARED_LIB_EXPORT shared_hello();
diff --git a/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp b/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp
new file mode 100644
index 000000000..2820d5d02
--- /dev/null
+++ b/Tests/InstallMode/subpro_b_shared_lib/src/shared_lib.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+
+#include <shared_lib.h>
+
+using namespace std;
+
+void shared_hello()
+{
+ cout << "Hello from shared_lib" << endl;
+}
diff --git a/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt
new file mode 100644
index 000000000..e397c02e1
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.20.0)
+
+project(subpro_c_nested_lib LANGUAGES NONE)
+
+include(../Subproject.cmake)
+add_subproject(c1_lib DIR subsubpro_c1_lib)
+add_subproject(c2_lib DIR subsubpro_c2_lib
+ DEPENDS
+ c1_lib
+)
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt
new file mode 100644
index 000000000..89f375559
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/CMakeLists.txt
@@ -0,0 +1,61 @@
+# This CMakeLists.txt is a nested subproject of the
+# subproject C (ExternalProject_Add).
+
+cmake_minimum_required(VERSION 3.20)
+project(c1_lib_project VERSION 1.2.3 LANGUAGES CXX)
+
+include(GNUInstallDirs)
+
+add_library(the_c1_lib STATIC
+ "include/c1_lib.h"
+ "src/c1_lib.cpp"
+)
+
+target_include_directories(the_c1_lib PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+)
+
+install(
+ TARGETS
+ the_c1_lib
+ EXPORT main
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+)
+
+set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
+
+include(CMakePackageConfigHelpers)
+
+configure_package_config_file(
+ "cmake/PackageConfig.cmake.in"
+ "${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}"
+ PATH_VARS
+ CMAKE_INSTALL_INCLUDEDIR
+ CMAKE_INSTALL_LIBDIR
+)
+
+write_basic_package_version_file("${PROJECT_NAME}Version.cmake"
+ VERSION "${PROJECT_VERSION}"
+ COMPATIBILITY SameMajorVersion
+)
+
+install(
+ EXPORT main
+ FILE "${PROJECT_NAME}Targets.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
+
+install(
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in
new file mode 100644
index 000000000..0fe72c91f
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/cmake/PackageConfig.cmake.in
@@ -0,0 +1,8 @@
+set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
+
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+
+set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
+set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h
new file mode 100644
index 000000000..245f9d48c
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/include/c1_lib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void c1_hello();
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp
new file mode 100644
index 000000000..c405056eb
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c1_lib/src/c1_lib.cpp
@@ -0,0 +1,10 @@
+#include <iostream>
+
+#include <c1_lib.h>
+
+using namespace std;
+
+void c1_hello()
+{
+ cout << "Hello from c1_lib" << endl;
+}
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt
new file mode 100644
index 000000000..7580c778c
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/CMakeLists.txt
@@ -0,0 +1,71 @@
+# This CMakeLists.txt is a nested subproject of the
+# subproject C (ExternalProject_Add).
+
+cmake_minimum_required(VERSION 3.20)
+project(c2_lib_project VERSION 1.2.3 LANGUAGES CXX)
+
+find_package(c1_lib_project REQUIRED)
+
+include(GNUInstallDirs)
+
+add_library(the_c2_lib STATIC
+ "include/c2_lib.h"
+ "src/c2_lib.cpp"
+)
+
+target_link_libraries(the_c2_lib
+ PUBLIC
+ the_c1_lib
+)
+
+# This is to fix an issue on AIX/GCC (see commit 4fc47424)
+set_property(TARGET the_c2_lib PROPERTY NO_SYSTEM_FROM_IMPORTED 1)
+
+target_include_directories(the_c2_lib PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
+)
+
+install(
+ TARGETS
+ the_c2_lib
+ EXPORT main
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+)
+
+set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
+
+include(CMakePackageConfigHelpers)
+
+configure_package_config_file(
+ "cmake/PackageConfig.cmake.in"
+ "${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}"
+ PATH_VARS
+ CMAKE_INSTALL_INCLUDEDIR
+ CMAKE_INSTALL_LIBDIR
+)
+
+write_basic_package_version_file("${PROJECT_NAME}Version.cmake"
+ VERSION "${PROJECT_VERSION}"
+ COMPATIBILITY SameMajorVersion
+)
+
+install(
+ EXPORT main
+ FILE "${PROJECT_NAME}Targets.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
+
+install(
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Version.cmake"
+ DESTINATION "${INSTALL_CMAKE_DIR}"
+)
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in
new file mode 100644
index 000000000..45a177a53
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/cmake/PackageConfig.cmake.in
@@ -0,0 +1,11 @@
+set(@PROJECT_NAME@_VERSION @PROJECT_VERSION@)
+
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+
+set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
+set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
+
+include(CMakeFindDependencyMacro)
+find_dependency(c1_lib_project REQUIRED)
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h
new file mode 100644
index 000000000..5056814f4
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/include/c2_lib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void c2_hello();
diff --git a/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp
new file mode 100644
index 000000000..cd2c9321e
--- /dev/null
+++ b/Tests/InstallMode/subpro_c_nested_lib/subsubpro_c2_lib/src/c2_lib.cpp
@@ -0,0 +1,12 @@
+#include <iostream>
+
+#include <c1_lib.h>
+#include <c2_lib.h>
+
+using namespace std;
+
+void c2_hello()
+{
+ cout << "Hello from c2_lib and also..." << endl;
+ c1_hello();
+}
diff --git a/Tests/InstallMode/subpro_d_executable/CMakeLists.txt b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt
new file mode 100644
index 000000000..60189e228
--- /dev/null
+++ b/Tests/InstallMode/subpro_d_executable/CMakeLists.txt
@@ -0,0 +1,27 @@
+# This CMakeLists.txt is part of the subproject B (ExternalProject_Add).
+
+cmake_minimum_required(VERSION 3.20)
+project(subpro_d_executable LANGUAGES CXX)
+
+find_package(static_lib_project REQUIRED)
+find_package(shared_lib_project REQUIRED)
+find_package(c2_lib_project REQUIRED)
+
+add_executable(the_executable
+ "src/main.cpp"
+)
+
+target_link_libraries(the_executable PRIVATE
+ the_static_lib
+ the_shared_lib
+ the_c2_lib
+)
+
+# This is to fix an issue on AIX/GCC (see commit 4fc47424)
+set_property(TARGET the_executable PROPERTY NO_SYSTEM_FROM_IMPORTED 1)
+
+install(
+ TARGETS
+ the_executable
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+)
diff --git a/Tests/InstallMode/subpro_d_executable/src/main.cpp b/Tests/InstallMode/subpro_d_executable/src/main.cpp
new file mode 100644
index 000000000..ec12004af
--- /dev/null
+++ b/Tests/InstallMode/subpro_d_executable/src/main.cpp
@@ -0,0 +1,13 @@
+#include <cstdlib>
+
+#include <c2_lib.h>
+#include <shared_lib.h>
+#include <static_lib.h>
+
+int main()
+{
+ static_hello();
+ shared_hello();
+ c2_hello();
+ return EXIT_SUCCESS;
+}
diff --git a/Tests/InstallMode/superpro/CMakeLists.txt b/Tests/InstallMode/superpro/CMakeLists.txt
new file mode 100644
index 000000000..ae4d25c1f
--- /dev/null
+++ b/Tests/InstallMode/superpro/CMakeLists.txt
@@ -0,0 +1,29 @@
+# This CMakeLists.txt is part of the superproject (add_subdirectory).
+
+# Below file transfers are executed at configuration time!
+
+file(
+ COPY
+ "file_copy.txt"
+ DESTINATION
+ "${CMAKE_INSTALL_PREFIX}"
+)
+
+file(COPY_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/file_copy_file.txt"
+ "${CMAKE_INSTALL_PREFIX}/file_copy_file.txt"
+)
+
+file(
+ INSTALL
+ "file_install.txt"
+ DESTINATION
+ "${CMAKE_INSTALL_PREFIX}"
+)
+
+file(
+ CREATE_LINK
+ "${CMAKE_CURRENT_SOURCE_DIR}/file_create_link_symbolic.txt"
+ "${CMAKE_INSTALL_PREFIX}/file_create_link_symbolic.txt"
+ SYMBOLIC
+)
diff --git a/Tests/InstallMode/superpro/file_copy.txt b/Tests/InstallMode/superpro/file_copy.txt
new file mode 100644
index 000000000..aacbb9644
--- /dev/null
+++ b/Tests/InstallMode/superpro/file_copy.txt
@@ -0,0 +1 @@
+This file should always be copied into CMAKE_INSTALL_PREFIX.
diff --git a/Tests/InstallMode/superpro/file_copy_file.txt b/Tests/InstallMode/superpro/file_copy_file.txt
new file mode 100644
index 000000000..aacbb9644
--- /dev/null
+++ b/Tests/InstallMode/superpro/file_copy_file.txt
@@ -0,0 +1 @@
+This file should always be copied into CMAKE_INSTALL_PREFIX.
diff --git a/Tests/InstallMode/superpro/file_create_link_symbolic.txt b/Tests/InstallMode/superpro/file_create_link_symbolic.txt
new file mode 100644
index 000000000..16a481ba1
--- /dev/null
+++ b/Tests/InstallMode/superpro/file_create_link_symbolic.txt
@@ -0,0 +1,2 @@
+This file should always be installed into CMAKE_INSTALL_PREFIX
+as a symbolic link to the original file.
diff --git a/Tests/InstallMode/superpro/file_install.txt b/Tests/InstallMode/superpro/file_install.txt
new file mode 100644
index 000000000..eac97823b
--- /dev/null
+++ b/Tests/InstallMode/superpro/file_install.txt
@@ -0,0 +1,6 @@
+This file should be placed in CMAKE_INSTALL_PREFIX
+as a copy if the CMAKE_INSTALL_MODE environment variable
+is unset or equals "COPY".
+If the variable's value is "SYMLINK" or "SYMLINK_OR_COPY",
+the CMAKE_INSTALL_PREFIX should rather receive a symbolic
+link to this file.
diff --git a/Tests/MSManifest/Subdir/CMakeLists.txt b/Tests/MSManifest/Subdir/CMakeLists.txt
index 8664572c6..3b4fccc1b 100644
--- a/Tests/MSManifest/Subdir/CMakeLists.txt
+++ b/Tests/MSManifest/Subdir/CMakeLists.txt
@@ -7,4 +7,8 @@ if(MSVC AND NOT MSVC_VERSION LESS 1400)
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
add_executable(MSManifestNone main.c)
set_property(TARGET MSManifestNone PROPERTY LINK_FLAGS "/MANIFEST:NO")
+elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang")
+ add_test(NAME MSManifest.Single COMMAND
+ ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifest>
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
endif()
diff --git a/Tests/MSManifest/Subdir2/CMakeLists.txt b/Tests/MSManifest/Subdir2/CMakeLists.txt
index 19d8de73a..0d960ad51 100644
--- a/Tests/MSManifest/Subdir2/CMakeLists.txt
+++ b/Tests/MSManifest/Subdir2/CMakeLists.txt
@@ -6,7 +6,7 @@ add_executable(MSMultipleManifest main.c
${CMAKE_CURRENT_BINARY_DIR}/test_manifest2.manifest
${CMAKE_CURRENT_BINARY_DIR}/test_manifest3.manifest)
-if(MSVC AND NOT MSVC_VERSION LESS 1400)
+if((MSVC AND NOT MSVC_VERSION LESS 1400) OR (WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang") )
add_test(NAME MSManifest.Multiple COMMAND
${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSMultipleManifest>
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake)
diff --git a/Tests/Qt6Autogen/CMakeLists.txt b/Tests/Qt6Autogen/CMakeLists.txt
new file mode 100644
index 000000000..a603b5081
--- /dev/null
+++ b/Tests/Qt6Autogen/CMakeLists.txt
@@ -0,0 +1,8 @@
+# Set Qt test version and include the Autogen test macros
+set(QT_TEST_VERSION 6)
+include("../QtAutogen/TestMacros.cmake")
+
+# Common tests
+include("../QtAutogen/Tests.cmake")
+
+set(TEST_BUILD_DIRS "${TEST_BUILD_DIRS}" PARENT_SCOPE)
diff --git a/Tests/QtAutogen/AutogenCoreTest.cmake b/Tests/QtAutogen/AutogenCoreTest.cmake
index 580385928..e62a6aac4 100644
--- a/Tests/QtAutogen/AutogenCoreTest.cmake
+++ b/Tests/QtAutogen/AutogenCoreTest.cmake
@@ -21,27 +21,27 @@ if (QT_TEST_VERSION EQUAL 4)
qt4_generate_moc(${ARGN})
endmacro()
-elseif(QT_TEST_VERSION EQUAL 5)
+elseif(QT_TEST_VERSION GREATER_EQUAL 5)
- find_package(Qt5Core REQUIRED)
+ find_package(Qt${QT_TEST_VERSION}Core REQUIRED)
- set(QT_QTCORE_TARGET Qt5::Core)
- set(QT_LIBRARIES Qt5::Core)
+ set(QT_QTCORE_TARGET Qt${QT_TEST_VERSION}::Core)
+ set(QT_LIBRARIES Qt${QT_TEST_VERSION}::Core)
# Include directories
- include_directories(${Qt5Core_INCLUDE_DIRS})
+ include_directories(${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS})
# Definitions
- if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
+ if(Qt${QT_TEST_VERSION}_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC})
endif()
# Qt macros
macro(qtx_wrap_cpp)
- qt5_wrap_cpp(${ARGN})
+ cmake_language(CALL qt${QT_TEST_VERSION}_wrap_cpp ${ARGN})
endmacro()
macro(qtx_generate_moc)
- qt5_generate_moc(${ARGN})
+ cmake_language(CALL qt${QT_TEST_VERSION}_generate_moc ${ARGN})
endmacro()
else()
diff --git a/Tests/QtAutogen/AutogenGuiTest.cmake b/Tests/QtAutogen/AutogenGuiTest.cmake
index b76d341a4..e5eb7510c 100644
--- a/Tests/QtAutogen/AutogenGuiTest.cmake
+++ b/Tests/QtAutogen/AutogenGuiTest.cmake
@@ -21,27 +21,27 @@ if (QT_TEST_VERSION EQUAL 4)
qt4_generate_moc(${ARGN})
endmacro()
-elseif(QT_TEST_VERSION EQUAL 5)
+elseif(QT_TEST_VERSION GREATER_EQUAL 5)
- find_package(Qt5Widgets REQUIRED)
+ find_package(Qt${QT_TEST_VERSION}Widgets REQUIRED)
- set(QT_QTCORE_TARGET Qt5::Core)
- set(QT_LIBRARIES Qt5::Widgets)
+ set(QT_QTCORE_TARGET Qt${QT_TEST_VERSION}::Core)
+ set(QT_LIBRARIES Qt${QT_TEST_VERSION}::Widgets)
# Include directories
- include_directories(${Qt5Widgets_INCLUDE_DIRS})
+ include_directories(${Qt${QT_TEST_VERSION}Widgets_INCLUDE_DIRS})
# Definitions
- if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
+ if(Qt${QT_TEST_VERSION}_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC})
endif()
# Qt macros
macro(qtx_wrap_cpp)
- qt5_wrap_cpp(${ARGN})
+ cmake_language(CALL qt${QT_TEST_VERSION}_wrap_cpp ${ARGN})
endmacro()
macro(qtx_generate_moc)
- qt5_generate_moc(${ARGN})
+ cmake_language(CALL qt${QT_TEST_VERSION}_generate_moc ${ARGN})
endmacro()
else()
diff --git a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
index 17855ffd8..cac680f87 100644
--- a/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
+++ b/Tests/QtAutogen/AutogenOriginDependsOff/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.11)
+cmake_minimum_required(VERSION 3.16)
project(AutogenOriginDependsOff)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt b/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt
index 5aabe0e68..37ce90b93 100644
--- a/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt
+++ b/Tests/QtAutogen/AutogenOriginDependsOn/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(AutogenOriginDependsOn)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt b/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt
index 492b5dbd3..cf3f15567 100644
--- a/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt
+++ b/Tests/QtAutogen/AutogenTargetDepends/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(AutogenTargetDepends)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/Complex/CMakeLists.txt b/Tests/QtAutogen/Complex/CMakeLists.txt
index d9fdf5cf4..8a9a5d29a 100644
--- a/Tests/QtAutogen/Complex/CMakeLists.txt
+++ b/Tests/QtAutogen/Complex/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Complex)
include("../AutogenGuiTest.cmake")
@@ -16,6 +16,8 @@ add_library(privateSlot OBJECT private_slot.cpp)
# Pass Qt compiler features to targets that don't link against Qt
target_compile_features(codeeditorLib PRIVATE ${QT_COMPILE_FEATURES})
target_compile_features(privateSlot PRIVATE ${QT_COMPILE_FEATURES})
+target_link_libraries(codeeditorLib PRIVATE ${QT_LIBRARIES})
+target_link_libraries(privateSlot PRIVATE ${QT_LIBRARIES})
configure_file(generated_resource.qrc.in generated_resource.qrc @ONLY)
add_custom_command(
diff --git a/Tests/QtAutogen/Complex/codeeditor.cpp b/Tests/QtAutogen/Complex/codeeditor.cpp
index 80d6a5509..9c9dbc323 100644
--- a/Tests/QtAutogen/Complex/codeeditor.cpp
+++ b/Tests/QtAutogen/Complex/codeeditor.cpp
@@ -70,7 +70,11 @@ int CodeEditor::lineNumberAreaWidth()
++digits;
}
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;
+#else
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
+#endif
return space;
}
diff --git a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
index e95c626e7..5c70e4336 100644
--- a/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
+++ b/Tests/QtAutogen/GlobalAutogenTarget/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.12)
+cmake_minimum_required(VERSION 3.16)
project(GlobalAutogenTarget)
include("../AutogenCoreTest.cmake")
@@ -74,6 +74,7 @@ execute_process(
-T "${CMAKE_GENERATOR_TOOLSET}"
"-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
WORKING_DIRECTORY "${GAT_BDIR}"
OUTPUT_VARIABLE output
diff --git a/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt b/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt
index 3925197fe..0e3df6f43 100644
--- a/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt
+++ b/Tests/QtAutogen/GlobalAutogenTarget/GAT/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.12)
+cmake_minimum_required(VERSION 3.16)
project(GAT)
include("../../AutogenCoreTest.cmake")
@@ -9,7 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
-# Disable ORIGN_DEPENDS and enable AUTOGEN global targets
+# Disable ORIGIN_DEPENDS and enable AUTOGEN global targets
set(CMAKE_AUTOGEN_ORIGIN_DEPENDS OFF)
set(CMAKE_GLOBAL_AUTOGEN_TARGET ON)
set(CMAKE_GLOBAL_AUTORCC_TARGET ON)
diff --git a/Tests/QtAutogen/MacOsFW/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/CMakeLists.txt
index c08efc47a..27c5f433b 100644
--- a/Tests/QtAutogen/MacOsFW/CMakeLists.txt
+++ b/Tests/QtAutogen/MacOsFW/CMakeLists.txt
@@ -1,21 +1,23 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MacOsFW)
include("../AutogenGuiTest.cmake")
-find_package(Qt5Test REQUIRED)
+find_package(Qt${QT_TEST_VERSION}Test REQUIRED)
+
+if(QT_TEST_VERSION EQUAL 5)
+ set(CMAKE_CXX_STANDARD 11)
+elseif(QT_TEST_VERSION EQUAL 6)
+ set(CMAKE_CXX_STANDARD 17)
+else()
+ message(FATAL_ERROR "Unsupported Qt version: ${QT_TEST_VERSION}")
+endif()
-set(CMAKE_CXX_STANDARD 11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output/lib)
set(CMAKE_INSTALL_NAME_DIR ${CMAKE_BINARY_DIR}/output/lib)
-if(POLICY CMP0042) # in CMake 3.0.0+
- set (CMAKE_MACOSX_RPATH OFF) # otherwise ON by default
-endif(POLICY CMP0042)
-
-if(POLICY CMP0068) # in CMake 3.9+
- cmake_policy(SET CMP0068 NEW)
-endif(POLICY CMP0068)
+set (CMAKE_MACOSX_RPATH OFF) # otherwise ON by default
+cmake_policy(SET CMP0068 NEW)
add_subdirectory(src)
add_subdirectory(test)
diff --git a/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt
index a02be00c5..67e2c8a8a 100644
--- a/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt
+++ b/Tests/QtAutogen/MacOsFW/src/CMakeLists.txt
@@ -9,7 +9,7 @@ set(MACOS_FW_LIB_HDRS
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
- ${Qt5Core_INCLUDE_DIRS}
+ ${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS}
)
add_library(macos_fw_lib SHARED
@@ -28,6 +28,4 @@ set_target_properties(macos_fw_lib PROPERTIES
POSITION_INDEPENDENT_CODE ON
PUBLIC_HEADER "${MACOS_FW_LIB_HDRS}"
)
-target_link_libraries(macos_fw_lib
- Qt5::Core
-)
+target_link_libraries(macos_fw_lib PRIVATE ${QT_QTCORE_TARGET})
diff --git a/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt b/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt
index 521c18450..8cb1bc531 100644
--- a/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt
+++ b/Tests/QtAutogen/MacOsFW/test/CMakeLists.txt
@@ -4,16 +4,16 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../src
)
include_directories(SYSTEM
- ${Qt5Core_INCLUDE_DIRS}
- ${Qt5Widgets_INCLUDE_DIRS}
+ ${Qt${QT_TEST_VERSION}Core_INCLUDE_DIRS}
+ ${Qt${QT_TEST_VERSION}Widgets_INCLUDE_DIRS}
)
set(testname AutomocMacosFWLib)
add_executable(${testname} testMacosFWLib.cpp)
set_target_properties(${testname} PROPERTIES AUTOMOC TRUE)
-target_link_libraries(${testname}
- Qt5::Core
- Qt5::Widgets
- Qt5::Test
+target_link_libraries(${testname} PRIVATE
+ Qt${QT_TEST_VERSION}::Core
+ Qt${QT_TEST_VERSION}::Widgets
+ Qt${QT_TEST_VERSION}::Test
macos_fw_lib
)
diff --git a/Tests/QtAutogen/ManySources/CMakeLists.txt b/Tests/QtAutogen/ManySources/CMakeLists.txt
index df8a2a662..f9ac7db41 100644
--- a/Tests/QtAutogen/ManySources/CMakeLists.txt
+++ b/Tests/QtAutogen/ManySources/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(ManySources)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/MocCMP0071/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/CMakeLists.txt
index 5c58a8278..7ab3a8eee 100644
--- a/Tests/QtAutogen/MocCMP0071/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0071/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocCMP0071)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt
index 954fe3dc1..4375b1778 100644
--- a/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0071/NEW/CMakeLists.txt
@@ -1,4 +1,3 @@
-cmake_minimum_required(VERSION 3.10)
cmake_policy(SET CMP0071 NEW)
# *Generate* files
diff --git a/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt b/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt
index 68fa06708..3771487b8 100644
--- a/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0071/OLD/CMakeLists.txt
@@ -1,4 +1,3 @@
-cmake_minimum_required(VERSION 3.10)
cmake_policy(SET CMP0071 OLD)
# *Generate* files
diff --git a/Tests/QtAutogen/MocCMP0100/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt
index 559cffe96..b19dc6aef 100644
--- a/Tests/QtAutogen/MocCMP0100/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0100/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocCMP0100)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt
index 654b31e29..aaaf7fbb6 100644
--- a/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0100/NEW/CMakeLists.txt
@@ -1,4 +1,3 @@
-cmake_minimum_required(VERSION 3.16)
cmake_policy(SET CMP0100 NEW)
add_executable(mocCMP0100New
diff --git a/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt
index 2be053504..006cda1b4 100644
--- a/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt
+++ b/Tests/QtAutogen/MocCMP0100/OLD/CMakeLists.txt
@@ -1,4 +1,3 @@
-cmake_minimum_required(VERSION 3.16)
cmake_policy(SET CMP0100 OLD)
# Generate moc files externally.
diff --git a/Tests/QtAutogen/MocInclude/CMakeLists.txt b/Tests/QtAutogen/MocInclude/CMakeLists.txt
index 04c8bafb7..4224d2f9c 100644
--- a/Tests/QtAutogen/MocInclude/CMakeLists.txt
+++ b/Tests/QtAutogen/MocInclude/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
+cmake_minimum_required(VERSION 3.16)
project(MocInclude)
get_filename_component(CS_REAL ${CMAKE_CURRENT_SOURCE_DIR} REALPATH)
include("${CS_REAL}/../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt b/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt
index 8b11b465d..c28616bfc 100644
--- a/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt
+++ b/Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.15)
+cmake_minimum_required(VERSION 3.16)
project(MocIncludeSymlink)
include("../AutogenCoreTest.cmake")
@@ -63,6 +63,7 @@ macro(buildMocInclude sourceDir binaryDir)
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOMOC_PATH_PREFIX=ON"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/MocMacroName/CMakeLists.txt b/Tests/QtAutogen/MocMacroName/CMakeLists.txt
index bf13d187d..d8dc4a33d 100644
--- a/Tests/QtAutogen/MocMacroName/CMakeLists.txt
+++ b/Tests/QtAutogen/MocMacroName/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocMacroName)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocOnly/CMakeLists.txt b/Tests/QtAutogen/MocOnly/CMakeLists.txt
index f4fde58e7..b5d405a1e 100644
--- a/Tests/QtAutogen/MocOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/MocOnly/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocOnly)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocOptions/CMakeLists.txt b/Tests/QtAutogen/MocOptions/CMakeLists.txt
index 19ee6587e..169e6cbe8 100644
--- a/Tests/QtAutogen/MocOptions/CMakeLists.txt
+++ b/Tests/QtAutogen/MocOptions/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocOptions)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/MocOsMacros/CMakeLists.txt b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt
index b0125f6c3..db44da318 100644
--- a/Tests/QtAutogen/MocOsMacros/CMakeLists.txt
+++ b/Tests/QtAutogen/MocOsMacros/CMakeLists.txt
@@ -1,10 +1,10 @@
-cmake_minimum_required(VERSION 3.11)
+cmake_minimum_required(VERSION 3.16)
project(MocOsMacros)
include("../AutogenCoreTest.cmake")
# Tests if moc processes Q_OS_XXX macros
-message( "Qt5Core_VERSION: ${Qt5Core_VERSION}" )
+message( "Qt${QT_TEST_VERSION}Core_VERSION: ${Qt${QT_TEST_VERSION}Core_VERSION}" )
message(
"CMAKE_CXX_COMPILER_PREDEFINES_COMMAND: "
${CMAKE_CXX_COMPILER_PREDEFINES_COMMAND} )
@@ -12,7 +12,7 @@ message(
# On some platforms (e.g. MAC) Q_OS_XXX requires moc to include moc_predefs.h
# which is supported since Qt 5.8 and requires
# CMAKE_CXX_COMPILER_PREDEFINES_COMMAND to be defined.
-if( ( ${Qt5Core_VERSION} VERSION_GREATER_EQUAL "5.8" ) AND
+if( ( ${Qt${QT_TEST_VERSION}Core_VERSION} VERSION_GREATER_EQUAL "5.8" ) AND
DEFINED CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
)
message( "Test enabled!" )
diff --git a/Tests/QtAutogen/MocSkipSource/CMakeLists.txt b/Tests/QtAutogen/MocSkipSource/CMakeLists.txt
index c88673618..b9e20c84c 100644
--- a/Tests/QtAutogen/MocSkipSource/CMakeLists.txt
+++ b/Tests/QtAutogen/MocSkipSource/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocSkipSource)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt b/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt
index e8af6c983..88d099897 100644
--- a/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt
+++ b/Tests/QtAutogen/ObjectLibrary/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(ObjectLibrary)
include("../AutogenCoreTest.cmake")
@@ -11,7 +11,7 @@ add_subdirectory(a)
# Object library b defined locally
include_directories(b)
add_library(b OBJECT b/classb.cpp)
-target_compile_features(b PRIVATE ${QT_COMPILE_FEATURES})
+target_link_libraries(b PRIVATE ${QT_LIBRARIES})
# Executable with OBJECT library generator expressions
add_executable(someProgram main.cpp $<TARGET_OBJECTS:a> $<TARGET_OBJECTS:b>)
diff --git a/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt b/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt
index fe76ac32c..5ace3aeda 100644
--- a/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt
+++ b/Tests/QtAutogen/ObjectLibrary/a/CMakeLists.txt
@@ -1,2 +1,2 @@
add_library(a OBJECT classa.cpp)
-target_compile_features(a PRIVATE ${QT_COMPILE_FEATURES})
+target_link_libraries(a PRIVATE ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/Parallel/CMakeLists.txt b/Tests/QtAutogen/Parallel/CMakeLists.txt
index 299bcbfd7..29628ebf8 100644
--- a/Tests/QtAutogen/Parallel/CMakeLists.txt
+++ b/Tests/QtAutogen/Parallel/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Parallel)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/Parallel1/CMakeLists.txt b/Tests/QtAutogen/Parallel1/CMakeLists.txt
index 5c7d547df..d94aba547 100644
--- a/Tests/QtAutogen/Parallel1/CMakeLists.txt
+++ b/Tests/QtAutogen/Parallel1/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Parallel1)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/Parallel2/CMakeLists.txt b/Tests/QtAutogen/Parallel2/CMakeLists.txt
index 668aea4bd..58667a85b 100644
--- a/Tests/QtAutogen/Parallel2/CMakeLists.txt
+++ b/Tests/QtAutogen/Parallel2/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Parallel2)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/Parallel3/CMakeLists.txt b/Tests/QtAutogen/Parallel3/CMakeLists.txt
index 5c50f5ee5..cc3aae006 100644
--- a/Tests/QtAutogen/Parallel3/CMakeLists.txt
+++ b/Tests/QtAutogen/Parallel3/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Parallel3)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/Parallel4/CMakeLists.txt b/Tests/QtAutogen/Parallel4/CMakeLists.txt
index 2c40c6a67..2b81e9853 100644
--- a/Tests/QtAutogen/Parallel4/CMakeLists.txt
+++ b/Tests/QtAutogen/Parallel4/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(Parallel4)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt b/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt
index cddece37a..5543b9aaa 100644
--- a/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt
+++ b/Tests/QtAutogen/ParallelAUTO/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(ParallelAUTO)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/RccEmpty/CMakeLists.txt b/Tests/QtAutogen/RccEmpty/CMakeLists.txt
index a8e2af1b6..c8f9d17cf 100644
--- a/Tests/QtAutogen/RccEmpty/CMakeLists.txt
+++ b/Tests/QtAutogen/RccEmpty/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RccEmpty)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt b/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt
index 61b9601a2..b44973d8d 100644
--- a/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt
+++ b/Tests/QtAutogen/RccOffMocLibrary/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RccOffMocLibrary)
include("../AutogenCoreTest.cmake")
@@ -9,9 +9,7 @@ include("../AutogenCoreTest.cmake")
add_library(empty STATIC empty.cpp not_generated_file.qrc)
set_target_properties(empty PROPERTIES AUTORCC OFF)
set_target_properties(empty PROPERTIES AUTOMOC TRUE)
-target_link_libraries(empty no_link_language)
+target_link_libraries(empty PRIVATE no_link_language ${QT_LIBRARIES})
add_library(no_link_language STATIC empty.h)
set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE)
-# Pass Qt compiler features to targets that don't link against Qt
-target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES})
-target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES})
+target_link_libraries(no_link_language PRIVATE ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/RccOnly/CMakeLists.txt b/Tests/QtAutogen/RccOnly/CMakeLists.txt
index f3776f575..f3271e07c 100644
--- a/Tests/QtAutogen/RccOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/RccOnly/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RccOnly)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RccSkipSource/CMakeLists.txt b/Tests/QtAutogen/RccSkipSource/CMakeLists.txt
index 42232744f..a79177fe5 100644
--- a/Tests/QtAutogen/RccSkipSource/CMakeLists.txt
+++ b/Tests/QtAutogen/RccSkipSource/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RccSkipSource)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
index c53e857e7..76dbdf50e 100644
--- a/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocBasic/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RerunMocBasic)
include("../AutogenCoreTest.cmake")
@@ -63,6 +63,7 @@ execute_process(
${_D_CMAKE_GENERATOR_INSTANCE}
"-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
RESULT_VARIABLE exit_code
OUTPUT_VARIABLE output
diff --git a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
index 42f2f57c5..e27a8242d 100644
--- a/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocBasic/MocBasic/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocBasic)
include("../../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt
index 26776595d..3a9244d2f 100644
--- a/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt
@@ -1,6 +1,6 @@
# This test checks whether adding a source file to the project triggers an AUTOMOC re-run.
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RerunMocOnAddFile)
include("../AutogenCoreTest.cmake")
@@ -64,6 +64,7 @@ try_compile(MOC_RERUN
MocOnAddFile
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in
index 9e5e21c30..e600137fb 100644
--- a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in
+++ b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocOnAddFile)
include("@CMAKE_CURRENT_LIST_DIR@/../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt
index c5811ebce..b17e4c54e 100644
--- a/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt
@@ -1,6 +1,6 @@
# This test checks whether a missing dependency of the moc output triggers an AUTOMOC re-run.
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RerunMocOnMissingDependency)
include("../AutogenCoreTest.cmake")
@@ -13,10 +13,10 @@ add_executable(exe "${main_source}")
set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/MocOnMissingDependency")
set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency")
set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency-build")
-if(DEFINED Qt5Core_VERSION AND Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
- set(moc_depfiles_supported TRUE)
+if(DEFINED Qt${QT_TEST_VERSION}Core_VERSION AND Qt${QT_TEST_VERSION}Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
+ set(moc_depfiles_supported TRUE)
else()
- set(moc_depfiles_supported FALSE)
+ set(moc_depfiles_supported FALSE)
endif()
# Utility macros
@@ -48,6 +48,7 @@ try_compile(MOC_RERUN
MocOnMissingDependency
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=ON"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt b/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt
index a7fb2d7f7..2d2edb497 100644
--- a/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocPlugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RerunMocPlugin)
include("../AutogenCoreTest.cmake")
@@ -63,6 +63,7 @@ try_compile(MOC_PLUGIN
MocPlugin
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt
index 506828976..8097fd033 100644
--- a/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunMocPlugin/MocPlugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(MocPlugin)
include("../../AutogenGuiTest.cmake")
@@ -22,7 +22,7 @@ configure_file(jsonIn/StyleE.json jsonFiles/StyleE_Custom.json)
set(CMAKE_AUTOMOC TRUE)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles")
-link_libraries(Qt5::Widgets)
+link_libraries(Qt${QT_TEST_VERSION}::Widgets)
add_library(PlugA STATIC StyleA.cpp)
add_library(PlugB STATIC StyleB.cpp)
diff --git a/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt b/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt
index 33c01acbe..1598bfd58 100644
--- a/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunRccConfigChange/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.11.2)
+cmake_minimum_required(VERSION 3.16)
project(RerunRccConfigChange)
include("../AutogenCoreTest.cmake")
@@ -33,6 +33,7 @@ try_compile(RCC_DEPENDS
RccConfigChange
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt b/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt
index e2dd0ac38..83f3a45c0 100644
--- a/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunRccConfigChange/RccConfigChange/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.11.2)
+cmake_minimum_required(VERSION 3.16)
project(RccConfigChange)
include("../../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
index 1301550f2..15e38db72 100644
--- a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RerunRccDepends)
include("../AutogenCoreTest.cmake")
@@ -66,6 +66,7 @@ try_compile(RCC_DEPENDS
RccDepends
CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
OUTPUT_VARIABLE output
)
diff --git a/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt
index 150f849b3..6bba16396 100644
--- a/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunRccDepends/RccDepends/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(RccDepends)
include("../../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
index 9b114e9be..979e87857 100644
--- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt
@@ -66,6 +66,7 @@ execute_process(
"${build_type_extra}"
"-DQT_TEST_VERSION=${QT_TEST_VERSION}"
"-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
"-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
RESULT_VARIABLE exit_code
OUTPUT_VARIABLE output
diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
index c787db1d5..177572599 100644
--- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
+++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(UicOnFileChange)
include("@CMAKE_CURRENT_LIST_DIR@/../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt b/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt
index f3536ba2c..25ea82204 100644
--- a/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt
+++ b/Tests/QtAutogen/StaticLibraryCycle/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(StaticLibraryCycle)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/TestMacros.cmake b/Tests/QtAutogen/TestMacros.cmake
index 9dcf31fbd..529592e85 100644
--- a/Tests/QtAutogen/TestMacros.cmake
+++ b/Tests/QtAutogen/TestMacros.cmake
@@ -7,8 +7,17 @@ else()
endif()
list(APPEND Autogen_BUILD_OPTIONS
"-DCMAKE_AUTOGEN_VERBOSE=1"
- "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
)
+if(Qt${QT_TEST_VERSION}Core_DIR)
+ get_filename_component(prefix "${Qt${QT_TEST_VERSION}Core_DIR}" DIRECTORY)
+ get_filename_component(prefix "${prefix}" DIRECTORY)
+ get_filename_component(prefix "${prefix}" DIRECTORY)
+ list(APPEND Autogen_BUILD_OPTIONS "-DCMAKE_PREFIX_PATH:STRING=${prefix}")
+else()
+ list(APPEND Autogen_BUILD_OPTIONS
+ "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+ )
+endif()
# XXX(xcode-per-cfg-src): Drop the NO_PER_CONFIG_SOURCES exclusion
# when the Xcode generator supports per-config sources.
if(CMAKE_GENERATOR STREQUAL "Xcode")
diff --git a/Tests/QtAutogen/UicInclude/CMakeLists.txt b/Tests/QtAutogen/UicInclude/CMakeLists.txt
index 929868b52..042d18f5e 100644
--- a/Tests/QtAutogen/UicInclude/CMakeLists.txt
+++ b/Tests/QtAutogen/UicInclude/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(UicInclude)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/UicInterface/CMakeLists.txt b/Tests/QtAutogen/UicInterface/CMakeLists.txt
index e0227645b..167ae49c2 100644
--- a/Tests/QtAutogen/UicInterface/CMakeLists.txt
+++ b/Tests/QtAutogen/UicInterface/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(UicInterface)
include("../AutogenGuiTest.cmake")
@@ -11,12 +11,12 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_library(KI18n klocalizedstring.cpp)
-target_link_libraries(KI18n ${QT_QTCORE_TARGET})
+target_link_libraries(KI18n PRIVATE ${QT_QTCORE_TARGET})
set(autouic_options
-tr tr2$<$<NOT:$<BOOL:$<TARGET_PROPERTY:NO_KUIT_SEMANTIC>>>:x>i18n
)
-if (NOT Qt5Widgets_VERSION VERSION_LESS 5.3.0)
+if (NOT Qt${QT_TEST_VERSION}Widgets_VERSION VERSION_LESS 5.3.0)
list(APPEND autouic_options -include klocalizedstring.h)
endif()
diff --git a/Tests/QtAutogen/UicNoGui/CMakeLists.txt b/Tests/QtAutogen/UicNoGui/CMakeLists.txt
index 076299db1..b938a17c6 100644
--- a/Tests/QtAutogen/UicNoGui/CMakeLists.txt
+++ b/Tests/QtAutogen/UicNoGui/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.16)
project(UicNoGui)
include("../AutogenCoreTest.cmake")
diff --git a/Tests/QtAutogen/UicOnly/CMakeLists.txt b/Tests/QtAutogen/UicOnly/CMakeLists.txt
index b16325438..e25b44d27 100644
--- a/Tests/QtAutogen/UicOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/UicOnly/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(UicOnly)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/QtAutogen/UicSkipSource/CMakeLists.txt b/Tests/QtAutogen/UicSkipSource/CMakeLists.txt
index dc3b7d4eb..15dfe6563 100644
--- a/Tests/QtAutogen/UicSkipSource/CMakeLists.txt
+++ b/Tests/QtAutogen/UicSkipSource/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.16)
project(UicSkipSource)
include("../AutogenGuiTest.cmake")
diff --git a/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake
index 8fa6041b9..6d26f99c7 100644
--- a/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake
+++ b/Tests/RunCMake/Autogen/CMP0111-imported-target-prelude.cmake
@@ -1,6 +1,6 @@
enable_language(CXX)
-find_package(Qt5 REQUIRED COMPONENTS Core)
+find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core)
# Detect `-NOTFOUND` libraries at generate time.
cmake_policy(SET CMP0111 NEW)
diff --git a/Tests/RunCMake/Autogen/CMakeLists.txt b/Tests/RunCMake/Autogen/CMakeLists.txt
index 9a66cde9b..2632ffa91 100644
--- a/Tests/RunCMake/Autogen/CMakeLists.txt
+++ b/Tests/RunCMake/Autogen/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.16)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/Autogen/QtInFunction.cmake b/Tests/RunCMake/Autogen/QtInFunction.cmake
index a44bc5ab4..6c42cc232 100644
--- a/Tests/RunCMake/Autogen/QtInFunction.cmake
+++ b/Tests/RunCMake/Autogen/QtInFunction.cmake
@@ -1,9 +1,9 @@
enable_language(CXX)
function (use_autogen target)
- find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
- set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE)
- set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE)
+ find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets)
+ set(Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}" PARENT_SCOPE)
+ set(Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}" PARENT_SCOPE)
set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
set_property(TARGET "${target}" PROPERTY AUTORCC 1)
set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
diff --git a/Tests/RunCMake/Autogen/QtInFunctionNested.cmake b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake
index 5421ba00d..2e7b8add3 100644
--- a/Tests/RunCMake/Autogen/QtInFunctionNested.cmake
+++ b/Tests/RunCMake/Autogen/QtInFunctionNested.cmake
@@ -1,9 +1,9 @@
enable_language(CXX)
function (use_autogen target)
- find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
- set(Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}" PARENT_SCOPE)
- set(Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}" PARENT_SCOPE)
+ find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets)
+ set(Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}" PARENT_SCOPE)
+ set(Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}" PARENT_SCOPE)
set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
set_property(TARGET "${target}" PROPERTY AUTORCC 1)
set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
diff --git a/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake
index 35f1cd16c..d9296c44c 100644
--- a/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake
+++ b/Tests/RunCMake/Autogen/QtInFunctionProperty.cmake
@@ -1,13 +1,13 @@
enable_language(CXX)
function (use_autogen target)
- find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
+ find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
PROPERTY
- Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}")
+ Qt${with_qt_version}Core_VERSION_MAJOR "${Qt${with_qt_version}Core_VERSION_MAJOR}")
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
PROPERTY
- Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MINOR}")
+ Qt${with_qt_version}Core_VERSION_MINOR "${Qt${with_qt_version}Core_VERSION_MINOR}")
set_property(TARGET "${target}" PROPERTY AUTOMOC 1)
set_property(TARGET "${target}" PROPERTY AUTORCC 1)
set_property(TARGET "${target}" PROPERTY AUTOUIC 1)
diff --git a/Tests/RunCMake/Autogen/RunCMakeTest.cmake b/Tests/RunCMake/Autogen/RunCMakeTest.cmake
index bbcbd5ed8..e4c581146 100644
--- a/Tests/RunCMake/Autogen/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Autogen/RunCMakeTest.cmake
@@ -1,7 +1,13 @@
include(RunCMake)
run_cmake(NoQt)
-if (with_qt5)
+if (DEFINED with_qt_version)
+ set(RunCMake_TEST_OPTIONS
+ -Dwith_qt_version=${with_qt_version}
+ "-DQt${with_qt_version}_DIR:PATH=${Qt${with_qt_version}_DIR}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
+ )
+
run_cmake(QtInFunction)
run_cmake(QtInFunctionNested)
run_cmake(QtInFunctionProperty)
diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt
new file mode 100644
index 000000000..bbc08e6f4
--- /dev/null
+++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.21)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt
new file mode 100644
index 000000000..f0f2efc27
--- /dev/null
+++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar-build-stdout.txt
@@ -0,0 +1 @@
+This message is printed by echo_message.bat
diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake
new file mode 100644
index 000000000..63d6068a9
--- /dev/null
+++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CheckEnvironmentVar.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_MSVCIDE_RUN_PATH "${CMAKE_SOURCE_DIR}")
+add_custom_target(main COMMAND echo_message)
diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake
new file mode 100644
index 000000000..a424ff214
--- /dev/null
+++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CheckEnvironmentVar-build)
+run_cmake(CheckEnvironmentVar)
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake_command(CheckEnvironmentVar-build ${CMAKE_COMMAND} --build . --config Debug --target main)
+unset(RunCMake_TEST_BINARY_DIR)
+unset(RunCMake_TEST_NO_CLEAN)
diff --git a/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat
new file mode 100755
index 000000000..92c60173a
--- /dev/null
+++ b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/echo_message.bat
@@ -0,0 +1 @@
+echo This message is printed by echo_message.bat
diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt
index 15b56a10d..15b56a10d 100644
--- a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake
new file mode 100644
index 000000000..5a2b01885
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake
@@ -0,0 +1,9 @@
+include(CMakeDependentOption)
+
+cmake_policy(SET CMP0127 NEW)
+
+set(A 1)
+set(B 1)
+set(C 0)
+cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt
new file mode 100644
index 000000000..b16e84b78
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/CMakeDependentOption.cmake:[0-9]+ \(message\):
+ Policy CMP0127 is not set: cmake_dependent_option\(\) supports full Condition
+ Syntax. Run "cmake --help-policy CMP0127" for policy details. Use the
+ cmake_policy command to set the policy and suppress this warning.
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake:[0-9]+ \(cmake_dependent_option\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt
new file mode 100644
index 000000000..d89dbd3db
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt
@@ -0,0 +1,2 @@
+-- USE_FOO='OFF'
+-- USE_BAR='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake
new file mode 100644
index 000000000..00d440d37
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake
@@ -0,0 +1,9 @@
+include(CMakeDependentOption)
+
+set(A 1)
+set(B 1)
+set(C 0)
+cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
+cmake_dependent_option(USE_BAR "Use Bar" ON "A;B" OFF)
+message(STATUS "USE_BAR='${USE_BAR}'")
diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt
new file mode 100644
index 000000000..15b56a10d
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt
@@ -0,0 +1 @@
+-- USE_FOO='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake
new file mode 100644
index 000000000..e92c1e697
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake
@@ -0,0 +1,7 @@
+include(CMakeDependentOption)
+
+cmake_policy(SET CMP0127 NEW)
+
+set(FOO "lower")
+cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES \"(UPPER|lower)\"" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt
new file mode 100644
index 000000000..15b56a10d
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt
@@ -0,0 +1 @@
+-- USE_FOO='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/Regex.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake
index 8342a01b7..81df003d9 100644
--- a/Tests/RunCMake/CMakeDependentOption/Regex.cmake
+++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake
@@ -1,5 +1,7 @@
include(CMakeDependentOption)
+cmake_policy(SET CMP0127 OLD)
+
set(FOO "lower")
cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES (UPPER|lower)" OFF)
message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
index e1045f231..61e046f89 100644
--- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake
@@ -1,3 +1,6 @@
include(RunCMake)
-run_cmake_script(Regex)
+run_cmake_script(Regex-CMP0127-NEW)
+run_cmake_script(Regex-CMP0127-OLD)
+run_cmake_script(Parentheses-CMP0127-NEW)
+run_cmake_script(Parentheses-CMP0127-WARN)
diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt
new file mode 100644
index 000000000..15b56a10d
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt
@@ -0,0 +1 @@
+-- USE_FOO='ON'
diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake
new file mode 100644
index 000000000..6db2128e3
--- /dev/null
+++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake
@@ -0,0 +1,6 @@
+include(CMakeDependentOption)
+
+set(A1 1)
+set(bb 1)
+cmake_dependent_option(USE_FOO "Use Foo" ON "A1;bb" OFF)
+message(STATUS "USE_FOO='${USE_FOO}'")
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 86cb849fe..e24ef5850 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -151,8 +151,23 @@ endif()
if(CMAKE_GENERATOR MATCHES "Make")
add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU})
endif()
-if(CMake_TEST_Qt5)
+unset(ninja_test_with_qt_version)
+unset(ninja_qt_args)
+if(CMake_TEST_Qt6)
+ find_package(Qt6Widgets QUIET NO_MODULE)
+ if(Qt6Widgets_FOUND)
+ set(ninja_test_with_qt_version 6)
+ # Work around Qt6 not finding sibling dependencies without CMAKE_PREFIX_PATH
+ cmake_path(GET Qt6_DIR PARENT_PATH base_dir) # <base>/lib/cmake
+ cmake_path(GET base_dir PARENT_PATH base_dir) # <base>/lib
+ cmake_path(GET base_dir PARENT_PATH base_dir) # <base>
+ set(ninja_qt_args -DCMAKE_PREFIX_PATH=${base_dir})
+ endif()
+elseif(CMake_TEST_Qt5)
find_package(Qt5Widgets QUIET NO_MODULE)
+ if(Qt5Widgets_FOUND)
+ set(ninja_test_with_qt_version 5)
+ endif()
endif()
if(CMAKE_GENERATOR MATCHES "Ninja")
set(Ninja_ARGS
@@ -162,18 +177,27 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
if(CMAKE_Fortran_COMPILER)
list(APPEND Ninja_ARGS -DTEST_Fortran=1)
endif()
- if(CMake_TEST_Qt5 AND Qt5Core_FOUND)
- list(APPEND Ninja_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION})
- if(Qt5Widgets_FOUND)
- list(APPEND Ninja_ARGS -DQt5Widgets_DIR=${Qt5Widgets_DIR})
- endif()
+ if(ninja_test_with_qt_version)
+ list(APPEND Ninja_ARGS
+ -DCMake_TEST_Qt_version=${ninja_test_with_qt_version}
+ -DQt${ninja_test_with_qt_version}_DIR=${Qt${ninja_test_with_qt_version}_DIR}
+ -DQt${ninja_test_with_qt_version}Core_DIR=${Qt${ninja_test_with_qt_version}Core_DIR}
+ -DCMake_TEST_Qt${ninja_test_with_qt_version}Core_Version=${Qt${ninja_test_with_qt_version}Core_VERSION}
+ -DQt${ninja_test_with_qt_version}Widgets_DIR=${Qt${ninja_test_with_qt_version}Widgets_DIR}
+ ${ninja_qt_args}
+ )
endif()
add_RunCMake_test(Ninja)
set(NinjaMultiConfig_ARGS
-DCYGWIN=${CYGWIN} -DMSYS=${MSYS}
)
- if(CMake_TEST_Qt5 AND Qt5Core_FOUND)
- list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_Qt5=1 -DQt5Core_DIR=${Qt5Core_DIR} -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION})
+ if(ninja_test_with_qt_version)
+ list(APPEND NinjaMultiConfig_ARGS
+ -DCMake_TEST_Qt_version=${ninja_test_with_qt_version}
+ -DQt${ninja_test_with_qt_version}Core_DIR=${Qt${ninja_test_with_qt_version}Core_DIR}
+ -DCMake_TEST_Qt${ninja_test_with_qt_version}Core_Version=${Qt${ninja_test_with_qt_version}Core_VERSION}
+ ${ninja_qt_args}
+ )
endif()
if(DEFINED CMake_TEST_CUDA)
list(APPEND NinjaMultiConfig_ARGS -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
@@ -205,11 +229,29 @@ add_RunCMake_test(AndroidTestUtilities)
if(CMake_TEST_APPLE_SILICON)
add_RunCMake_test(AppleSilicon)
endif()
-set(autogen_with_qt5 FALSE)
+set(want_NoQt_test TRUE)
+if(CMake_TEST_Qt6 AND Qt6Widgets_FOUND)
+ # Work around Qt6 not finding sibling dependencies without CMAKE_PREFIX_PATH
+ cmake_path(GET Qt6_DIR PARENT_PATH base_dir) # <base>/lib/cmake
+ cmake_path(GET base_dir PARENT_PATH base_dir) # <base>/lib
+ cmake_path(GET base_dir PARENT_PATH base_dir) # <base>
+ add_RunCMake_test(AutogenQt6 TEST_DIR Autogen
+ -Dwith_qt_version=6
+ "-DQt6_DIR:PATH=${Qt6_DIR}"
+ "-DCMAKE_PREFIX_PATH:STRING=${base_dir}"
+ )
+ set(want_NoQt_test FALSE)
+endif ()
if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
- set(autogen_with_qt5 TRUE)
+ add_RunCMake_test(AutogenQt5 TEST_DIR Autogen
+ -Dwith_qt_version=5
+ "-DQt5_DIR:PATH=${Qt5_DIR}"
+ )
+ set(want_NoQt_test FALSE)
endif ()
-add_RunCMake_test(Autogen -Dwith_qt5=${autogen_with_qt5})
+if(want_NoQt_test)
+ add_RunCMake_test(AutogenNoQt TEST_DIR Autogen)
+endif()
add_RunCMake_test(ArtifactOutputDirs)
@@ -310,7 +352,7 @@ add_RunCMake_test(TargetProperties)
add_RunCMake_test(ToolchainFile)
add_RunCMake_test(find_dependency)
add_RunCMake_test(CompileDefinitions)
-add_RunCMake_test(CompileFeatures)
+add_RunCMake_test(CompileFeatures -DCMake_NO_C_STANDARD=${CMake_NO_C_STANDARD} -DCMake_NO_CXX_STANDARD=${CMake_NO_CXX_STANDARD})
add_RunCMake_test(Policy)
add_RunCMake_test(PolicyScope)
add_RunCMake_test(WriteBasicConfigVersionFile)
@@ -349,6 +391,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
endif()
add_RunCMake_test(execute_process)
add_RunCMake_test(export)
+add_RunCMake_test(cmake_host_system_information)
add_RunCMake_test(cmake_language)
add_RunCMake_test(cmake_minimum_required)
add_RunCMake_test(cmake_parse_arguments)
@@ -374,12 +417,11 @@ add_RunCMake_test(ctest_disabled_test)
add_RunCMake_test(ctest_skipped_test)
add_RunCMake_test(ctest_update)
add_RunCMake_test(ctest_upload)
+add_RunCMake_test(ctest_environment)
add_RunCMake_test(ctest_fixtures)
-add_RunCMake_test(file -DMSYS=${MSYS})
+add_RunCMake_test(file -DCYGWIN=${CYGWIN} -DMSYS=${MSYS})
add_RunCMake_test(file-CHMOD -DMSYS=${MSYS})
-if(HAVE_ELF_H OR CMAKE_SYSTEM_NAME STREQUAL "AIX")
- add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DHAVE_ELF_H=${HAVE_ELF_H})
-endif()
+add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
add_RunCMake_test(find_file)
add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS})
add_RunCMake_test(find_package -DMSYS=${MSYS})
@@ -557,6 +599,7 @@ if(CMake_TEST_FindGTK2)
endif()
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
+ add_RunCMake_test(CMAKE_MSVCIDE_RUN_PATH)
add_RunCMake_test(include_external_msproject -DVS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME})
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio (9|10)" AND NOT CMAKE_VS_DEVENV_COMMAND)
set(NO_USE_FOLDERS 1)
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index 746ff8b1c..7997c785f 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -7,6 +7,7 @@ include("${RunCMake_SOURCE_DIR}/CPackTestHelpers.cmake")
run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM.CUSTOM_BINARY_SPEC_FILE" false "MONOLITHIC;COMPONENT")
run_cpack_test(CUSTOM_NAMES "RPM.CUSTOM_NAMES;DEB.CUSTOM_NAMES;TGZ;DragNDrop" true "COMPONENT")
run_cpack_test(DEBUGINFO "RPM.DEBUGINFO;DEB.DEBUGINFO" true "COMPONENT")
+run_cpack_test(DEBUGINFO "DEB.DEBUGINFO" true "MONOLITHIC")
run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM.DEFAULT_PERMISSIONS;DEB.DEFAULT_PERMISSIONS" false "MONOLITHIC;COMPONENT")
run_cpack_test(DEPENDENCIES "RPM.DEPENDENCIES;DEB.DEPENDENCIES" true "COMPONENT")
run_cpack_test(DIST "RPM.DIST" false "MONOLITHIC")
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
index cf4aa510a..b3e64857f 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
@@ -1,8 +1,5 @@
set(whitespaces_ "[\t\n\r ]*")
-set(EXPECTED_FILES_COUNT "6")
-set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-
if(GENERATOR_TYPE STREQUAL "RPM")
set(NAME "Debuginfo")
set(DEBUG_SUFFIX "debuginfo")
@@ -15,30 +12,49 @@ elseif(GENERATOR_TYPE STREQUAL "DEB")
set(DEBUG_PKG "ddeb")
endif()
-set(EXPECTED_FILE_1_NAME "${NAME}")
-set(EXPECTED_FILE_1_COMPONENT "applications")
-set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
+set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}")
-set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+ set(EXPECTED_FILES_COUNT "6")
-set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}")
-set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
+ set(EXPECTED_FILE_1_NAME "${NAME}")
+ set(EXPECTED_FILE_1_COMPONENT "applications")
+ set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
-set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}")
-if(GENERATOR_TYPE STREQUAL "RPM")
- set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*")
-elseif(GENERATOR_TYPE STREQUAL "DEB")
- set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*")
-endif()
+ set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.${PKG}")
+ set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
-if(GENERATOR_TYPE STREQUAL "RPM")
- set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
- set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
-elseif(GENERATOR_TYPE STREQUAL "DEB")
- set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb")
- set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*")
-endif()
+ set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.${PKG}")
+ set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
+
+ set(EXPECTED_FILE_4 "${NAME}-applications-${DEBUG_SUFFIX}*.${DEBUG_PKG}")
+ if(GENERATOR_TYPE STREQUAL "RPM")
+ set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*\.debug.*")
+ elseif(GENERATOR_TYPE STREQUAL "DEB")
+ set(EXPECTED_FILE_CONTENT_4 ".*/usr/lib/debug/.build-id/.*\.debug.*")
+ endif()
+
+ if(GENERATOR_TYPE STREQUAL "RPM")
+ set(EXPECTED_FILE_5 "libs-DebugInfoPackage.rpm")
+ set(EXPECTED_FILE_CONTENT_5 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/test_lib.cpp.*\.debug.*")
+ elseif(GENERATOR_TYPE STREQUAL "DEB")
+ set(EXPECTED_FILE_5 "TestDinfo-pkg-libs-dbgsym.ddeb")
+ set(EXPECTED_FILE_CONTENT_5 ".*/usr/lib/debug/.build-id/.*\.debug.*")
+ endif()
+
+ set(EXPECTED_FILE_6 "TestDinfo-pkg*-appheaders.${PKG}")
+ set(EXPECTED_FILE_CONTENT_6_LIST "/include;/include/test_lib.hpp")
-set(EXPECTED_FILE_6 "TestDinfo-pkg*-appheaders.${PKG}")
-set(EXPECTED_FILE_CONTENT_6_LIST "/include;/include/test_lib.hpp")
+elseif(PACKAGING_TYPE STREQUAL "MONOLITHIC" AND GENERATOR_TYPE STREQUAL "DEB")
+ set(EXPECTED_FILES_COUNT "2")
+
+ set(EXPECTED_FILE_1 "TestDinfo-pkg.deb")
+ set(
+ EXPECTED_FILE_CONTENT_1_LIST
+ "/bar;/bar/CMakeLists.txt;/bas;/bas/libtest_lib.so;/foo;/foo/test_prog;/include;/include/test_lib.hpp"
+ )
+
+ set(EXPECTED_FILE_2 "TestDinfo-pkg-dbgsym.ddeb")
+ set(EXPECTED_FILE_CONTENT_2 ".*/usr/lib/debug/.build-id/.*\.debug.*")
+
+endif()
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
index 9ff1f8a04..e9cebbf8d 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake
@@ -28,6 +28,8 @@ install(TARGETS test_prog DESTINATION foo COMPONENT applications)
install(FILES CMakeLists.txt DESTINATION bar COMPONENT headers)
install(TARGETS test_lib DESTINATION bas COMPONENT libs)
+set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON)
+
set(CPACK_RPM_APPLICATIONS_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_APPLICATIONS_DEBUGINFO_PACKAGE ON)
set(CPACK_DEBIAN_APPLICATIONS_FILE_NAME "DEB-DEFAULT")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt
index 37360e8f2..8b6ca94d0 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt
+++ b/Tests/RunCMake/CPack/tests/EXTRA/DEB-stderr.txt
@@ -1,6 +1,6 @@
CPack Warning: Adding file to tar:
-#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/bas
+#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/[^/]+/DEB/extra-0.1.1-[^/]+/bas
#missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles
CPack Warning: Adding file to tar:
-#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/Linux/DEB/extra-0.1.1-Linux/foo
+#top level directory: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/_CPack_Packages/[^/]+/DEB/extra-0.1.1-[^/]+/foo
#missing file: .*/Tests/RunCMake/DEB.EXTRA/CPack/EXTRA-build/conffiles
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
index d1a3a5fb2..f8592151e 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/bar;/bar/CMakeLists.txt;/baz;/baz/CMakeLists.txt;/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
index fbdda9c88..13af09773 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake
@@ -1,3 +1,4 @@
set(whitespaces_ "[\t\n\r ]*")
-set(md5sums_md5sums "^.* usr/foo/CMakeLists\.txt${whitespaces_}$")
+set(hashsyms_ "[a-f0-9]+")
+set(md5sums_md5sums "^${hashsyms_} usr/bar/CMakeLists\.txt${whitespaces_}${hashsyms_} usr/baz/CMakeLists\.txt${whitespaces_}${hashsyms_} usr/foo/CMakeLists\.txt${whitespaces_}$")
verifyDebControl("${FOUND_FILE_1}" "md5sums" "md5sums")
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake
index 15c589266..3c922d2ce 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake
@@ -1,4 +1,6 @@
install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
+install(FILES CMakeLists.txt DESTINATION bar COMPONENT test)
+install(FILES CMakeLists.txt DESTINATION baz COMPONENT test)
if(PACKAGING_TYPE STREQUAL "COMPONENT")
set(CPACK_COMPONENTS_ALL test)
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt
new file mode 100644
index 000000000..202ef80b6
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning:
+ The "Visual Studio 10 2010" generator is deprecated and will be removed in
+ a future version of CMake.
+
+ Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.$
diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake
diff --git a/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt b/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt
new file mode 100644
index 000000000..03b92a75c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvBuildType-stdout.txt
@@ -0,0 +1,2 @@
+-- ENV{CMAKE_BUILD_TYPE}='BuildTypeEnv'
+-- CMAKE_BUILD_TYPE='BuildTypeEnv'
diff --git a/Tests/RunCMake/CommandLine/EnvBuildType.cmake b/Tests/RunCMake/CommandLine/EnvBuildType.cmake
new file mode 100644
index 000000000..e5e6d04b8
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvBuildType.cmake
@@ -0,0 +1,2 @@
+message(STATUS "ENV{CMAKE_BUILD_TYPE}='$ENV{CMAKE_BUILD_TYPE}'")
+message(STATUS "CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'")
diff --git a/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt
new file mode 100644
index 000000000..4a2673299
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore-stdout.txt
@@ -0,0 +1,2 @@
+-- ENV{CMAKE_BUILD_TYPE}='BuildTypeEnv'
+-- CMAKE_BUILD_TYPE='BuildTypeOpt'
diff --git a/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake
new file mode 100644
index 000000000..f21666f73
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvBuildTypeIgnore.cmake
@@ -0,0 +1 @@
+include(EnvBuildType.cmake)
diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt b/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt
new file mode 100644
index 000000000..bfec18f9d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvConfigTypes-stdout.txt
@@ -0,0 +1,2 @@
+-- ENV{CMAKE_CONFIGURATION_TYPES}='ConfigTypesEnv'
+-- CMAKE_CONFIGURATION_TYPES='ConfigTypesEnv'
diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake b/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake
new file mode 100644
index 000000000..8c9b63a9a
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvConfigTypes.cmake
@@ -0,0 +1,2 @@
+message(STATUS "ENV{CMAKE_CONFIGURATION_TYPES}='$ENV{CMAKE_CONFIGURATION_TYPES}'")
+message(STATUS "CMAKE_CONFIGURATION_TYPES='${CMAKE_CONFIGURATION_TYPES}'")
diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt
new file mode 100644
index 000000000..7800a4f0d
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore-stdout.txt
@@ -0,0 +1,2 @@
+-- ENV{CMAKE_CONFIGURATION_TYPES}='ConfigTypesEnv'
+-- CMAKE_CONFIGURATION_TYPES='ConfigTypesOpt'
diff --git a/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake
new file mode 100644
index 000000000..fcbbaea55
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/EnvConfigTypesIgnore.cmake
@@ -0,0 +1 @@
+include(EnvConfigTypes.cmake)
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index c58b1d06d..dc066f1d1 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -344,6 +344,26 @@ if(RunCMake_GENERATOR MATCHES "Unix Makefiles" OR RunCMake_GENERATOR MATCHES "Ni
run_EnvironmentExportCompileCommands()
endif()
+function(run_EnvironmentBuildType)
+ set(ENV{CMAKE_BUILD_TYPE} "BuildTypeEnv")
+ run_cmake(EnvBuildType)
+ run_cmake_with_options(EnvBuildTypeIgnore -DCMAKE_BUILD_TYPE=BuildTypeOpt)
+ unset(ENV{CMAKE_BUILD_TYPE})
+endfunction()
+
+function(run_EnvironmentConfigTypes)
+ set(ENV{CMAKE_CONFIGURATION_TYPES} "ConfigTypesEnv")
+ run_cmake(EnvConfigTypes)
+ run_cmake_with_options(EnvConfigTypesIgnore -DCMAKE_CONFIGURATION_TYPES=ConfigTypesOpt)
+ unset(ENV{CMAKE_CONFIGURATION_TYPES})
+endfunction()
+
+if(RunCMake_GENERATOR MATCHES "Make|^Ninja$")
+ run_EnvironmentBuildType()
+elseif(RunCMake_GENERATOR MATCHES "Ninja Multi-Config|Visual Studio|Xcode")
+ run_EnvironmentConfigTypes()
+endif()
+
function(run_EnvironmentToolchain)
set(ENV{CMAKE_TOOLCHAIN_FILE} "${RunCMake_SOURCE_DIR}/EnvToolchain-toolchain.cmake")
run_cmake(EnvToolchainAbsolute)
@@ -627,9 +647,10 @@ run_cmake_command(E_cat_directory
file(WRITE "${out}/first_file.txt" "first file to append\n")
file(WRITE "${out}/second_file.txt" "second file to append\n")
+file(WRITE "${out}/empty_file.txt" "")
file(WRITE "${out}/unicode_file.txt" "àéùç - 한국어") # Korean in Korean
run_cmake_command(E_cat_good_cat
- ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/unicode_file.txt")
+ ${CMAKE_COMMAND} -E cat "${out}/first_file.txt" "${out}/second_file.txt" "${out}/empty_file.txt" "${out}/unicode_file.txt")
unset(out)
run_cmake_command(E_cat_good_binary_cat
@@ -898,3 +919,10 @@ set(ProfilingTestOutput ${RunCMake_TEST_BINARY_DIR}/output.json)
set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${ProfilingTestOutput})
run_cmake(ProfilingTest)
unset(RunCMake_TEST_OPTIONS)
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio 10 2010")
+ run_cmake_with_options(DeprecateVS10-WARN-ON -DCMAKE_WARN_VS10=ON)
+ unset(ENV{CMAKE_WARN_VS10})
+ run_cmake(DeprecateVS10-WARN-ON)
+ run_cmake_with_options(DeprecateVS10-WARN-OFF -DCMAKE_WARN_VS10=OFF)
+endif()
diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt
new file mode 100644
index 000000000..320c2bafe
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch-stderr.txt
@@ -0,0 +1,8 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+ Policy CMP0128 is not set: Selection of language standard and extension
+ flags improved\. Run "cmake --help-policy CMP0128" for policy details\. Use
+ the cmake_policy command to set the policy and suppress this warning\.
+
+ For compatibility with older versions of CMake, unnecessary flags for
+ language standard or compiler extensions may be added.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake
new file mode 100644
index 000000000..0a5606ac7
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnMatch.cmake
@@ -0,0 +1,7 @@
+enable_language(@lang@)
+cmake_policy(SET CMP0128 OLD)
+set(CMAKE_POLICY_WARNING_CMP0128 ON)
+
+set(CMAKE_@lang@_EXTENSIONS @extensions_default@)
+set(CMAKE_@lang@_STANDARD @standard_default@)
+add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@")
diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt
new file mode 100644
index 000000000..068cba9c2
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset-stderr.txt
@@ -0,0 +1,8 @@
+CMake Warning \(dev\) in CMakeLists\.txt:
+ Policy CMP0128 is not set: Selection of language standard and extension
+ flags improved\. Run "cmake --help-policy CMP0128" for policy details\. Use
+ the cmake_policy command to set the policy and suppress this warning\.
+
+ For compatibility with older versions of CMake, compiler extensions won't
+ be @opposite@\.
+This warning is for project developers\. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake
new file mode 100644
index 000000000..cd7af2c00
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/CMP0128WarnUnset.cmake
@@ -0,0 +1,6 @@
+enable_language(@lang@)
+cmake_policy(SET CMP0128 OLD)
+set(CMAKE_POLICY_WARNING_CMP0128 ON)
+
+set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@)
+add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@")
diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake
new file mode 100644
index 000000000..4e85397f4
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault-build-check.cmake
@@ -0,0 +1,12 @@
+foreach(flag @flags@)
+ string(FIND "${actual_stdout}" "${flag}" position)
+
+ if(NOT position EQUAL -1)
+ set(found TRUE)
+ break()
+ endif()
+endforeach()
+
+if(NOT found)
+ set(RunCMake_TEST_FAILED "No compile flags from \"@flags@\" found for LANG_STANDARD=default and @lang@_EXTENSIONS=@extensions_opposite@.")
+endif()
diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake
new file mode 100644
index 000000000..32578d1f9
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardDefault.cmake
@@ -0,0 +1,9 @@
+enable_language(@lang@)
+
+# Make sure the compile command is not hidden.
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+
+set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@)
+set(CMAKE_@lang@_STANDARD @standard_default@)
+add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@")
diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake
new file mode 100644
index 000000000..abe293c34
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset-build-check.cmake
@@ -0,0 +1,12 @@
+foreach(flag @flags@)
+ string(FIND "${actual_stdout}" "${flag}" position)
+
+ if(NOT position EQUAL -1)
+ set(found TRUE)
+ break()
+ endif()
+endforeach()
+
+if(NOT found)
+ set(RunCMake_TEST_FAILED "No compile flags from \"@flags@\" found for CMAKE_@lang@_EXTENSIONS=@extensions_opposite@.")
+endif()
diff --git a/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake
new file mode 100644
index 000000000..99bb3f069
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/ExtensionsStandardUnset.cmake
@@ -0,0 +1,8 @@
+enable_language(@lang@)
+
+# Make sure the compile command is not hidden.
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+
+set(CMAKE_@lang@_EXTENSIONS @extensions_opposite@)
+add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@")
diff --git a/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake
new file mode 100644
index 000000000..4f767fabd
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag-build-check.cmake
@@ -0,0 +1,8 @@
+foreach(flag @flags@)
+ string(FIND "${actual_stdout}" "${flag}" position)
+
+ if(NOT position EQUAL -1)
+ set(RunCMake_TEST_FAILED "\"${flag}\" compile flag found.")
+ break()
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake
new file mode 100644
index 000000000..8ef3a7206
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/NoUnnecessaryFlag.cmake
@@ -0,0 +1,9 @@
+enable_language(@lang@)
+
+# Make sure the compile command is not hidden.
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_@lang@_COMPILE_OBJECT "${CMAKE_@lang@_COMPILE_OBJECT}")
+
+set(CMAKE_@lang@_EXTENSIONS @extensions_default@)
+set(CMAKE_@lang@_STANDARD @standard_default@)
+add_library(foo "@RunCMake_SOURCE_DIR@/empty.@ext@")
diff --git a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
index 5a70da2fa..ebd981b3d 100644
--- a/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CompileFeatures/RunCMakeTest.cmake
@@ -9,17 +9,8 @@ run_cmake(NotAFeature_OriginDebugGenex)
run_cmake(NotAFeature_OriginDebugTransitive)
run_cmake(NotAFeature_OriginDebugCommand)
-run_cmake(generate_feature_list)
-file(READ
- "${RunCMake_BINARY_DIR}/generate_feature_list-build/c_features.txt"
- C_FEATURES
-)
-file(READ
- "${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx_features.txt"
- CXX_FEATURES
-)
-include("${RunCMake_BINARY_DIR}/generate_feature_list-build/c_standard_default.cmake")
-include("${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx_standard_default.cmake")
+run_cmake(compiler_introspection)
+include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake")
if (NOT C_FEATURES)
run_cmake(NoSupportedCFeatures)
@@ -43,21 +34,139 @@ elseif (cxx_std_98 IN_LIST CXX_FEATURES AND cxx_std_11 IN_LIST CXX_FEATURES)
unset(RunCMake_TEST_OPTIONS)
endif()
+configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt" "${RunCMake_BINARY_DIR}/CMakeLists.txt" COPYONLY)
+
+function(test_build)
+ set(test ${name}-${lang})
+
+ configure_file("${RunCMake_SOURCE_DIR}/${name}.cmake" "${RunCMake_BINARY_DIR}/${test}.cmake" @ONLY)
+ if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-build-check.cmake")
+ configure_file("${RunCMake_SOURCE_DIR}/${name}-build-check.cmake" "${RunCMake_BINARY_DIR}/${test}-build-check.cmake" @ONLY)
+ endif()
+ if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-stderr.txt")
+ configure_file("${RunCMake_SOURCE_DIR}/${name}-stderr.txt" "${RunCMake_BINARY_DIR}/${test}-stderr.txt" @ONLY)
+ endif()
+
+ set(RunCMake_SOURCE_DIR "${RunCMake_BINARY_DIR}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test}-build")
+ run_cmake(${test})
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . ${ARGN})
+endfunction()
+
+# Mangle flags such as they're in verbose build output.
+macro(mangle_flags variable)
+ set(result "${${variable}}")
+
+ if(RunCMake_GENERATOR MATCHES "Visual Studio" AND MSVC_TOOLSET_VERSION GREATER_EQUAL 141)
+ string(REPLACE "-" "/" result "${result}")
+ elseif(RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL 12)
+ string(REPLACE "=" [[\\=]] result "${result}")
+ endif()
+
+ string(REPLACE ";" " " result "${result}")
+ list(APPEND flags "${result}")
+endmacro()
+
+function(test_extensions_opposite)
+ if(extensions_opposite)
+ set(flag_ext "_EXT")
+ endif()
+
+ set(flag "${${lang}${${lang}_STANDARD_DEFAULT}${flag_ext}_FLAG}")
+
+ if(NOT flag)
+ return()
+ endif()
+
+ mangle_flags(flag)
+
+ # Make sure we enable/disable extensions when:
+ # 1. LANG_STANDARD is unset.
+ set(name ExtensionsStandardUnset)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0128=NEW)
+ test_build(--verbose)
+
+ # 2. LANG_STANDARD matches CMAKE_LANG_STANDARD_DEFAULT.
+ set(name ExtensionsStandardDefault)
+ test_build(--verbose)
+endfunction()
+
+function(test_no_unnecessary_flag)
+ set(standard_flag "${${lang}${${lang}_STANDARD_DEFAULT}_FLAG}")
+ set(extension_flag "${${lang}${${lang}_STANDARD_DEFAULT}_EXT_FLAG}")
+
+ if(NOT standard_flag AND NOT extension_flag)
+ return()
+ endif()
+
+ mangle_flags(standard_flag)
+ mangle_flags(extension_flag)
+
+ set(name NoUnnecessaryFlag)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0128=NEW)
+ test_build(--verbose)
+endfunction()
+
+function(test_cmp0128_warn_match)
+ set(name CMP0128WarnMatch)
+ test_build()
+endfunction()
+
+function(test_cmp0128_warn_unset)
+ # For compilers that had CMAKE_<LANG>_EXTENSION_COMPILE_OPTION (only IAR)
+ # there is no behavioural change and thus no warning.
+ if(NOT "${${lang}_EXT_FLAG}" STREQUAL "")
+ return()
+ endif()
+
+ if(extensions_opposite)
+ set(opposite "enabled")
+ else()
+ set(opposite "disabled")
+ endif()
+
+ set(name CMP0128WarnUnset)
+ test_build()
+endfunction()
+
+function(test_lang lang ext)
+ if(CMake_NO_${lang}_STANDARD)
+ return()
+ endif()
+
+ set(extensions_default "${${lang}_EXTENSIONS_DEFAULT}")
+ set(standard_default "${${lang}_STANDARD_DEFAULT}")
+
+ if(extensions_default)
+ set(extensions_opposite OFF)
+ else()
+ set(extensions_opposite ON)
+ endif()
+
+ test_extensions_opposite()
+ test_no_unnecessary_flag()
+ test_cmp0128_warn_match()
+ test_cmp0128_warn_unset()
+endfunction()
+
+if(C_STANDARD_DEFAULT)
+ test_lang(C c)
+endif()
+
if(CXX_STANDARD_DEFAULT)
run_cmake(NotAStandard)
foreach(standard 98 11)
- file(READ
- "${RunCMake_BINARY_DIR}/generate_feature_list-build/cxx${standard}_flag.txt"
- CXX${standard}_FLAG
- )
if (CXX${standard}_FLAG STREQUAL NOTFOUND)
run_cmake(RequireCXX${standard})
run_cmake(RequireCXX${standard}Variable)
endif()
- if (CXX${standard}EXT_FLAG STREQUAL NOTFOUND)
+ if (CXX${standard}_EXT_FLAG STREQUAL NOTFOUND)
run_cmake(RequireCXX${standard}Ext)
run_cmake(RequireCXX${standard}ExtVariable)
endif()
endforeach()
+
+ test_lang(CXX cpp)
endif()
diff --git a/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake
new file mode 100644
index 000000000..56913448a
--- /dev/null
+++ b/Tests/RunCMake/CompileFeatures/compiler_introspection.cmake
@@ -0,0 +1,38 @@
+enable_language(C CXX)
+
+set(info "")
+
+if(MSVC_TOOLSET_VERSION)
+ string(APPEND info "
+set(MSVC_TOOLSET_VERSION ${MSVC_TOOLSET_VERSION})
+
+")
+endif()
+
+if(CMAKE_XCODE_BUILD_SYSTEM)
+ string(APPEND info "
+set(CMAKE_XCODE_BUILD_SYSTEM ${CMAKE_XCODE_BUILD_SYSTEM})
+
+")
+endif()
+
+macro(info lang)
+ string(APPEND info "\
+set(${lang}_STANDARD_DEFAULT ${CMAKE_${lang}_STANDARD_DEFAULT})
+set(${lang}_EXTENSIONS_DEFAULT ${CMAKE_${lang}_EXTENSIONS_DEFAULT})
+set(${lang}_FEATURES ${CMAKE_${lang}_COMPILE_FEATURES})
+
+set(${lang}_EXT_FLAG ${CMAKE_${lang}_EXTENSION_COMPILE_OPTION})
+")
+
+ foreach(standard ${ARGN})
+ string(APPEND info "\
+set(${lang}${standard}_FLAG ${CMAKE_${lang}${standard}_STANDARD_COMPILE_OPTION})
+set(${lang}${standard}_EXT_FLAG ${CMAKE_${lang}${standard}_EXTENSION_COMPILE_OPTION})
+")
+ endforeach()
+endmacro()
+
+info(C 90 99 11 17 23)
+info(CXX 98 11 14 17 20 23)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")
diff --git a/Tests/RunCMake/CompileFeatures/empty.c b/Tests/RunCMake/CompileFeatures/empty.c
index 11ec041d1..8d91e77d3 100644
--- a/Tests/RunCMake/CompileFeatures/empty.c
+++ b/Tests/RunCMake/CompileFeatures/empty.c
@@ -1,7 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
- int empty()
+ int empty(void)
{
return 0;
}
diff --git a/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake b/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake
deleted file mode 100644
index 5c58052b8..000000000
--- a/Tests/RunCMake/CompileFeatures/generate_feature_list.cmake
+++ /dev/null
@@ -1,43 +0,0 @@
-
-enable_language(C)
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/c_features.txt"
- "${CMAKE_C_COMPILE_FEATURES}"
-)
-
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_features.txt"
- "${CMAKE_CXX_COMPILE_FEATURES}"
-)
-
-if(DEFINED CMAKE_C_STANDARD_DEFAULT)
- set(c_standard_default_code "set(C_STANDARD_DEFAULT \"${CMAKE_C_STANDARD_DEFAULT}\")\n")
-else()
- set(c_standard_default_code "unset(C_STANDARD_DEFAULT)\n")
-endif()
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/c_standard_default.cmake" "${c_standard_default_code}")
-
-if(DEFINED CMAKE_CXX_STANDARD_DEFAULT)
- set(cxx_standard_default_code "set(CXX_STANDARD_DEFAULT \"${CMAKE_CXX_STANDARD_DEFAULT}\")\n")
-else()
- set(cxx_standard_default_code "unset(CXX_STANDARD_DEFAULT)\n")
-endif()
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx_standard_default.cmake" "${cxx_standard_default_code}")
-
-foreach(standard 98 11)
- set(CXX${standard}_FLAG NOTFOUND)
- if (DEFINED CMAKE_CXX${standard}_STANDARD_COMPILE_OPTION)
- set(CXX${standard}_FLAG ${CMAKE_CXX${standard}_STANDARD_COMPILE_OPTION})
- endif()
-
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx${standard}_flag.txt"
- "${CXX${standard}_FLAG}"
- )
- set(CXX${standard}EXT_FLAG NOTFOUND)
- if (DEFINED CMAKE_CXX${standard}_EXTENSION_COMPILE_OPTION)
- set(CXX${standard}EXT_FLAG ${CMAKE_CXX${standard}_EXTENSION_COMPILE_OPTION})
- endif()
-
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cxx${standard}ext_flag.txt"
- "${CXX${standard}EXT_FLAG}"
- )
-endforeach()
diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
index 9baeab75e..e83c45e70 100644
--- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
@@ -9,6 +9,7 @@ run_cmake(DownloadTwice)
run_cmake(DownloadFile)
run_cmake(SameGenerator)
run_cmake(VarDefinitions)
+run_cmake(VarPassthroughs)
run_cmake(GetProperties)
run_cmake(UsesTerminalOverride)
run_cmake(MakeAvailable)
diff --git a/Tests/RunCMake/FetchContent/VarPassthroughs.cmake b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake
new file mode 100644
index 000000000..ad743d890
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/VarPassthroughs.cmake
@@ -0,0 +1,38 @@
+include(FetchContent)
+
+set(CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY AAAA)
+set(CMAKE_TLS_VERIFY BBBB)
+set(CMAKE_TLS_CAINFO CCCC)
+set(CMAKE_NETRC DDDD)
+set(CMAKE_NETRC_FILE EEEE)
+
+FetchContent_Declare(PassThrough
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed"
+)
+FetchContent_Populate(PassThrough)
+
+set(gen_file ${FETCHCONTENT_BASE_DIR}/passthrough-subbuild/CMakeLists.txt)
+if(NOT EXISTS ${gen_file})
+ message(FATAL_ERROR "File does not exist: ${gen_file}")
+endif()
+file(READ ${gen_file} contents)
+
+if(NOT contents MATCHES "CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY \\[==\\[AAAA\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY")
+endif()
+
+if(NOT contents MATCHES "CMAKE_TLS_VERIFY \\[==\\[BBBB\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_TLS_VERIFY")
+endif()
+
+if(NOT contents MATCHES "CMAKE_TLS_CAINFO \\[==\\[CCCC\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_TLS_CAINFO")
+endif()
+
+if(NOT contents MATCHES "CMAKE_NETRC \\[==\\[DDDD\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_NETRC")
+endif()
+
+if(NOT contents MATCHES "CMAKE_NETRC_FILE \\[==\\[EEEE\\]==\\]")
+ message(FATAL_ERROR "Missing CMAKE_NETRC_FILE")
+endif()
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake
new file mode 100644
index 000000000..e49ff22f6
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake
@@ -0,0 +1,17 @@
+if(WIN32)
+ set(ENV{PKG_CONFIG} "\"${CMAKE_CURRENT_SOURCE_DIR}\\dummy-pkg-config.bat\" --static --print-errors")
+else()
+ set(ENV{PKG_CONFIG} "\"${CMAKE_CURRENT_SOURCE_DIR}/dummy-pkg-config.sh\" --static --print-errors")
+endif()
+
+find_package(PkgConfig REQUIRED)
+
+if(NOT PKG_CONFIG_ARGN STREQUAL "--static;--print-errors")
+ message(SEND_ERROR "PKG_CONFIG_ARGN has wrong value '${PKG_CONFIG_ARGN}'")
+endif()
+
+_pkgconfig_invoke("none" "prefix" "output" "")
+
+if(NOT prefix_output STREQUAL "Received;--static;Received;--print-errors")
+ message(SEND_ERROR "prefix_output has wrong value '${prefix_output}'")
+endif()
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt
new file mode 100644
index 000000000..6615d805a
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-stdout.txt
@@ -0,0 +1,3 @@
+-- ZOT_LIBRARIES='zot'
+-- ZOT_LINK_LIBRARIES='[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib/prefix-zot-suffix'
+-- ZOT_LDFLAGS='-L[^']*/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH-build/zot/lib;-lzot'
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake
new file mode 100644
index 000000000..9f654b50a
--- /dev/null
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_LIBRARY_PATH.cmake
@@ -0,0 +1,29 @@
+find_package(PkgConfig REQUIRED)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig/zot.pc" "
+prefix=${CMAKE_CURRENT_BINARY_DIR}/zot
+libdir=\${prefix}/lib
+
+Name: Zot
+Description: Dummy packaget to test LIBRARY_DIR support
+Version: 1.0
+Libs: -L\${libdir} -lzot
+")
+
+# Create a "library" file to find in libdir.
+set(CMAKE_FIND_LIBRARY_PREFIXES "prefix-")
+set(CMAKE_FIND_LIBRARY_SUFFIXES "-suffix")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/prefix-zot-suffix")
+
+# 'pkg-config --libs' drops -L flags in PKG_CONFIG_SYSTEM_LIBRARY_PATH by default.
+set(ENV{PKG_CONFIG_SYSTEM_LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib")
+
+# 'pkgconf --libs' also drops -L flags in LIBRARY_PATH by default.
+set(ENV{LIBRARY_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib")
+
+set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}/zot/lib/pkgconfig")
+pkg_check_modules(ZOT REQUIRED zot)
+
+message(STATUS "ZOT_LIBRARIES='${ZOT_LIBRARIES}'")
+message(STATUS "ZOT_LINK_LIBRARIES='${ZOT_LINK_LIBRARIES}'")
+message(STATUS "ZOT_LDFLAGS='${ZOT_LDFLAGS}'")
diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
index 78ccd962f..f36d1eb85 100644
--- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
@@ -13,6 +13,7 @@ run_cmake(FindPkgConfig_PKGCONFIG_PATH)
run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH)
run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_ENVIRONMENT_PATH)
run_cmake(FindPkgConfig_extract_frameworks)
+run_cmake(FindPkgConfig_GET_MATCHING_ARGN)
if(APPLE)
run_cmake(FindPkgConfig_extract_frameworks_target)
@@ -31,4 +32,8 @@ if (PKG_CONFIG_FOUND)
run_cmake(FindPkgConfig_VERSION_OPERATORS)
run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME)
run_cmake(FindPkgConfig_empty_target)
+
+ if(NOT RunCMake_BINARY_DIR MATCHES " ")
+ run_cmake(FindPkgConfig_LIBRARY_PATH)
+ endif()
endif ()
diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
index 486977cbb..ed43f14be 100755
--- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
+++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat
@@ -1,5 +1,10 @@
@ECHO OFF
+rem variables to get around `--static --version` printing the received
+rem message and then version
+set static=false
+set print_errors=false
+
:LOOP
IF "%1"=="" (
@@ -21,7 +26,19 @@ IF "%1"=="--exists" (
EXIT /B 0
)
)
+IF "%1"=="--static" (
+ set static=true
+)
+IF "%1"=="--print-errors" (
+ set print_errors=true
+)
SHIFT
IF NOT "%~1"=="" GOTO LOOP
+IF "%static%"=="true" ECHO Received --static
+IF "%print_errors%"=="true" ECHO Received --print-errors
+
+IF "%static%"=="true" GOTO :EOF
+IF "%print_errors%"=="true" GOTO :EOF
+
EXIT /B 255
diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
index 56bba30dd..4021bf7a6 100755
--- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
+++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh
@@ -4,6 +4,11 @@
# to the --exists argument with the PKG_CONFIG_PATH environment variable
# and returns 1 if they are different.
+# variables to get around `--static --version` printing the received
+# message and then version
+static=false
+print_errors=false
+
while [ $# -gt 0 ]; do
case $1 in
--version)
@@ -17,7 +22,21 @@ while [ $# -gt 0 ]; do
echo "Found: ${PKG_CONFIG_PATH}"
[ "${last}" = "${PKG_CONFIG_PATH}" ] && exit 0 || exit 1
;;
+ --static)
+ static=true
+ ;;
+ --print-errors)
+ print_errors=true
+ ;;
esac
shift
done
+
+$static && echo "Received --static"
+$print_errors && echo "Received --print-errors"
+
+if $static || $print_errors; then
+ exit 0
+fi
+
exit 255
diff --git a/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt b/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt
new file mode 100644
index 000000000..cae367903
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/CMP0085-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning at CMakeLists.txt:[0-9]+ \(cmake_minimum_required\):
+ The OLD behavior for policy CMP0085 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.$
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt
new file mode 100644
index 000000000..385159d65
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-basic-stdout.txt
@@ -0,0 +1,7 @@
+Test project .*/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change
+ Test #1: basic\.case_foo
+ Test #2: basic\.case_bar
+ Test #3: basic\.disabled_case \(Disabled\)
+ Test #4: basic\.DISABLEDnot_really_case
+
+Total Tests: 4
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt
new file mode 100644
index 000000000..095fdcded
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change-typed-stdout.txt
@@ -0,0 +1,5 @@
+Test project .*/Tests/RunCMake/GoogleTest/GoogleTest-discovery-arg-change
+ Test #1: typed/short\.case
+ Test #2: typed/float\.case
+
+Total Tests: 2
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt
index eeecb6a7c..d06cd0a4d 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest-skip-timeout-stdout.txt
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-skip-test-stdout.txt
@@ -1,10 +1,10 @@
Test project .*
- Start 20: skip_test.test1
-1/1 Test #20: skip_test.test1 \.+\*\*\*Skipped +[0-9.]+ sec
+ Start 36: skip_test.test1
+1/1 Test #36: skip_test.test1 \.+\*\*\*Skipped +[0-9.]+ sec
100% tests passed, 0 tests failed out of 1
Total Test time \(real\) = +[0-9.]+ sec
The following tests did not run:
-.*20 - skip_test\.test1 \(Skipped\)
+.*36 - skip_test\.test1 \(Skipped\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
new file mode 100644
index 000000000..cf082670f
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
@@ -0,0 +1,16 @@
+Test project .*
+ Start 27: TEST:basic\.case_foo!3
+1/4 Test #27: TEST:basic\.case_foo!3 \.+ +Passed +[0-9.]+ sec
+ Start 28: TEST:basic\.case_bar!3
+2/4 Test #28: TEST:basic\.case_bar!3 \.+ +Passed +[0-9.]+ sec
+ Start 29: TEST:basic\.disabled_case!3
+3/4 Test #29: TEST:basic\.disabled_case!3 \.+\*+Not Run \(Disabled\) +[0-9.]+ sec
+ Start 30: TEST:basic\.DISABLEDnot_really_case!3
+4/4 Test #30: TEST:basic\.DISABLEDnot_really_case!3 \.+ +Passed +[0-9.]+ sec
+
+100% tests passed, 0 tests failed out of 3
+
+Total Test time \(real\) = +[0-9.]+ sec
+
+The following tests did not run:
+.*29 - TEST:basic.disabled_case!3 \(Disabled\)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt
new file mode 100644
index 000000000..4a9d75b78
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/GoogleTest-test4-stdout.txt
@@ -0,0 +1,9 @@
+Test project .*
+ Start 31: TEST:typed/short\.case!4
+1/2 Test #31: TEST:typed/short\.case!4 \.+ +Passed +[0-9.]+ sec
+ Start 32: TEST:typed/float\.case!4
+2/2 Test #32: TEST:typed/float\.case!4 \.+ +Passed +[0-9.]+ sec
+
+100% tests passed, 0 tests failed out of 2
+
+Total Test time \(real\) = +[0-9.]+ sec
diff --git a/Tests/RunCMake/GoogleTest/GoogleTest.cmake b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
index 8efd1171d..221d6adac 100644
--- a/Tests/RunCMake/GoogleTest/GoogleTest.cmake
+++ b/Tests/RunCMake/GoogleTest/GoogleTest.cmake
@@ -24,6 +24,24 @@ gtest_discover_tests(
PROPERTIES LABELS TEST2
)
+gtest_discover_tests(
+ fake_gtest
+ TEST_PREFIX TEST:
+ TEST_SUFFIX !3
+ TEST_FILTER basic*
+ EXTRA_ARGS how now "\"brown\" cow"
+ PROPERTIES LABELS TEST3
+)
+
+gtest_discover_tests(
+ fake_gtest
+ TEST_PREFIX TEST:
+ TEST_SUFFIX !4
+ TEST_FILTER typed*
+ EXTRA_ARGS how now "\"brown\" cow"
+ PROPERTIES LABELS TEST4
+)
+
add_executable(no_tests_defined no_tests_defined.cpp)
xcode_sign_adhoc(no_tests_defined)
diff --git a/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake
new file mode 100644
index 000000000..e4e13c5f7
--- /dev/null
+++ b/Tests/RunCMake/GoogleTest/GoogleTestDiscoveryArgChange.cmake
@@ -0,0 +1,14 @@
+enable_language(CXX)
+include(GoogleTest)
+
+enable_testing()
+
+include(xcode_sign_adhoc.cmake)
+
+add_executable(fake_gtest fake_gtest.cpp)
+xcode_sign_adhoc(fake_gtest)
+
+gtest_discover_tests(
+ fake_gtest
+ TEST_FILTER "${TEST_FILTER}*"
+)
diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
index 530c8abe5..33a4b4353 100644
--- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
@@ -1,5 +1,12 @@
include(RunCMake)
+if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR
+ RunCMake_GENERATOR STREQUAL "Watcom WMake")
+ set(fs_delay 3)
+else()
+ set(fs_delay 1.125)
+endif()
+
function(run_GoogleTest DISCOVERY_MODE)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-build)
@@ -40,6 +47,20 @@ function(run_GoogleTest DISCOVERY_MODE)
--no-label-summary
)
+ run_cmake_command(GoogleTest-test3
+ ${CMAKE_CTEST_COMMAND}
+ -C Debug
+ -L TEST3
+ --no-label-summary
+ )
+
+ run_cmake_command(GoogleTest-test4
+ ${CMAKE_CTEST_COMMAND}
+ -C Debug
+ -L TEST4
+ --no-label-summary
+ )
+
run_cmake_command(GoogleTest-test-missing
${CMAKE_CTEST_COMMAND}
-C Debug
@@ -139,6 +160,46 @@ function(run_GoogleTest_discovery_timeout DISCOVERY_MODE)
)
endfunction()
+function(run_GoogleTest_discovery_arg_change DISCOVERY_MODE)
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-arg-change)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+
+ run_cmake_with_options(GoogleTestDiscoveryArgChange
+ -DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE}
+ -DTEST_FILTER=basic
+ )
+ run_cmake_command(GoogleTest-discovery-arg-change-build
+ ${CMAKE_COMMAND}
+ --build .
+ --config Release
+ --target fake_gtest
+ )
+ run_cmake_command(GoogleTest-discovery-arg-change-basic
+ ${CMAKE_CTEST_COMMAND}
+ -C Release
+ -N
+ )
+ execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) # handle 1s resolution
+ run_cmake_with_options(GoogleTestDiscoveryArgChange
+ -DCMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE=${DISCOVERY_MODE}
+ -DTEST_FILTER=typed
+ )
+ run_cmake_command(GoogleTest-discovery-arg-change-build
+ ${CMAKE_COMMAND}
+ --build .
+ --config Release
+ --target fake_gtest
+ )
+ run_cmake_command(GoogleTest-discovery-arg-change-typed
+ ${CMAKE_CTEST_COMMAND}
+ -C Release
+ -N
+ )
+endfunction()
+
function(run_GoogleTest_discovery_multi_config)
# Use a single build tree for a few tests without cleaning.
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTest-discovery-multi-config)
@@ -181,6 +242,10 @@ foreach(DISCOVERY_MODE POST_BUILD PRE_TEST)
run_GoogleTestXML(${DISCOVERY_MODE})
message("Testing ${DISCOVERY_MODE} discovery mode via DISCOVERY_MODE option...")
run_GoogleTest_discovery_timeout(${DISCOVERY_MODE})
+ if(# VS 9 does not rebuild if POST_BUILD command changes.
+ NOT "${DISCOVERY_MODE};${RunCMake_GENERATOR}" MATCHES "^POST_BUILD;Visual Studio 9")
+ run_GoogleTest_discovery_arg_change(${DISCOVERY_MODE})
+ endif()
endforeach()
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
diff --git a/Tests/RunCMake/GoogleTest/fake_gtest.cpp b/Tests/RunCMake/GoogleTest/fake_gtest.cpp
index 1956c37fe..b2a5cb443 100644
--- a/Tests/RunCMake/GoogleTest/fake_gtest.cpp
+++ b/Tests/RunCMake/GoogleTest/fake_gtest.cpp
@@ -7,27 +7,42 @@ int main(int argc, char** argv)
// it only requires that we produces output in the expected format when
// invoked with --gtest_list_tests. Thus, we fake that here. This allows us
// to test the module without actually needing Google Test.
+ bool is_filtered =
+ argc > 2 && std::string(argv[2]).find("--gtest_filter=") == 0;
+ bool is_basic_only =
+ is_filtered && std::string(argv[2]).find("basic*") != std::string::npos;
+ bool is_typed_only =
+ is_filtered && std::string(argv[2]).find("typed*") != std::string::npos;
+
if (argc > 1 && std::string(argv[1]) == "--gtest_list_tests") {
- std::cout << "basic." << std::endl;
- std::cout << " case_foo" << std::endl;
- std::cout << " case_bar" << std::endl;
- std::cout << " DISABLED_disabled_case" << std::endl;
- std::cout << " DISABLEDnot_really_case" << std::endl;
- std::cout << "DISABLED_disabled." << std::endl;
- std::cout << " case" << std::endl;
- std::cout << "DISABLEDnotreally." << std::endl;
- std::cout << " case" << std::endl;
- std::cout << "typed/0. # TypeParam = short" << std::endl;
- std::cout << " case" << std::endl;
- std::cout << "typed/1. # TypeParam = float" << std::endl;
- std::cout << " case" << std::endl;
- std::cout << "value/test." << std::endl;
- std::cout << " case/0 # GetParam() = 1" << std::endl;
- std::cout << " case/1 # GetParam() = \"foo\"" << std::endl;
- std::cout << "param/special." << std::endl;
- std::cout << " case/0 # GetParam() = \"semicolon;\"" << std::endl;
- std::cout << " case/1 # GetParam() = \"backslash\\\"" << std::endl;
- std::cout << " case/2 # GetParam() = \"${var}\"" << std::endl;
+ if (!is_typed_only) {
+ std::cout << "basic." << std::endl;
+ std::cout << " case_foo" << std::endl;
+ std::cout << " case_bar" << std::endl;
+ std::cout << " DISABLED_disabled_case" << std::endl;
+ std::cout << " DISABLEDnot_really_case" << std::endl;
+ }
+ if (!is_basic_only && !is_typed_only) {
+ std::cout << "DISABLED_disabled." << std::endl;
+ std::cout << " case" << std::endl;
+ std::cout << "DISABLEDnotreally." << std::endl;
+ std::cout << " case" << std::endl;
+ }
+ if (!is_basic_only) {
+ std::cout << "typed/0. # TypeParam = short" << std::endl;
+ std::cout << " case" << std::endl;
+ std::cout << "typed/1. # TypeParam = float" << std::endl;
+ std::cout << " case" << std::endl;
+ }
+ if (!is_basic_only && !is_typed_only) {
+ std::cout << "value/test." << std::endl;
+ std::cout << " case/0 # GetParam() = 1" << std::endl;
+ std::cout << " case/1 # GetParam() = \"foo\"" << std::endl;
+ std::cout << "param/special." << std::endl;
+ std::cout << " case/0 # GetParam() = \"semicolon;\"" << std::endl;
+ std::cout << " case/1 # GetParam() = \"backslash\\\"" << std::endl;
+ std::cout << " case/2 # GetParam() = \"${var}\"" << std::endl;
+ }
return 0;
}
diff --git a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
deleted file mode 100644
index 46b840f4c..000000000
--- a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-enable_language(CXX)
-
-find_package(Qt5Core REQUIRED)
-
-set(CMAKE_AUTOMOC ON)
-
-add_library(simple_lib SHARED simple_lib.cpp)
-add_executable(app_with_qt app.cpp app_qt.cpp)
-target_link_libraries(app_with_qt PRIVATE simple_lib Qt5::Core)
-
-if(Qt5Widgets_DIR)
- find_package(Qt5Widgets REQUIRED)
- qt5_wrap_ui(_headers MyWindow.ui)
- add_executable(app_with_widget app.cpp MyWindow.cpp ${_headers})
- target_link_libraries(app_with_widget PRIVATE Qt5::Widgets)
- target_include_directories(app_with_widget PRIVATE "${CMAKE_BINARY_DIR}")
-endif()
-
-add_subdirectory(QtSubDir1)
-add_subdirectory(QtSubDir2)
-add_subdirectory(QtSubDir3)
diff --git a/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake b/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake
new file mode 100644
index 000000000..c44116969
--- /dev/null
+++ b/Tests/RunCMake/Ninja/QtAutoMocDeps.cmake
@@ -0,0 +1,27 @@
+enable_language(CXX)
+
+set(QtX Qt${with_qt_version})
+
+find_package(${QtX} REQUIRED COMPONENTS Core)
+
+set(CMAKE_AUTOMOC ON)
+
+add_library(simple_lib SHARED simple_lib.cpp)
+add_executable(app_with_qt app.cpp app_qt.cpp)
+target_link_libraries(app_with_qt PRIVATE simple_lib ${QtX}::Core)
+
+if(${QtX}Widgets_DIR)
+ find_package(${QtX} REQUIRED COMPONENTS Widgets)
+ if(with_qt_version STREQUAL 5)
+ qt5_wrap_ui(_headers MyWindow.ui)
+ else()
+ qt_wrap_ui(_headers MyWindow.ui)
+ endif()
+ add_executable(app_with_widget app.cpp MyWindow.cpp ${_headers})
+ target_link_libraries(app_with_widget PRIVATE ${QtX}::Widgets)
+ target_include_directories(app_with_widget PRIVATE "${CMAKE_BINARY_DIR}")
+endif()
+
+add_subdirectory(QtSubDir1)
+add_subdirectory(QtSubDir2)
+add_subdirectory(QtSubDir3)
diff --git a/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt
index 64016b683..3a12dcd6c 100644
--- a/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt
+++ b/Tests/RunCMake/Ninja/QtSubDir1/CMakeLists.txt
@@ -1,4 +1,4 @@
cmake_policy(SET CMP0116 OLD)
add_executable(sub_exe_1 ../app.cpp)
-target_link_libraries(sub_exe_1 PRIVATE Qt5::Core)
+target_link_libraries(sub_exe_1 PRIVATE ${QtX}::Core)
diff --git a/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt
index 3176426f4..a2f77e4d0 100644
--- a/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt
+++ b/Tests/RunCMake/Ninja/QtSubDir2/CMakeLists.txt
@@ -1,4 +1,4 @@
cmake_policy(SET CMP0116 NEW)
add_executable(sub_exe_2 ../app.cpp)
-target_link_libraries(sub_exe_2 PRIVATE Qt5::Core)
+target_link_libraries(sub_exe_2 PRIVATE ${QtX}::Core)
diff --git a/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt
index d38cfe076..70644fa7a 100644
--- a/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt
+++ b/Tests/RunCMake/Ninja/QtSubDir3/CMakeLists.txt
@@ -1,2 +1,2 @@
add_executable(sub_exe_3 ../app.cpp)
-target_link_libraries(sub_exe_3 PRIVATE Qt5::Core)
+target_link_libraries(sub_exe_3 PRIVATE ${QtX}::Core)
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 3f239b974..2a5b55620 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -319,12 +319,17 @@ function (run_ChangeBuildType)
endfunction()
run_ChangeBuildType()
-function(run_Qt5AutoMocDeps)
- if(CMake_TEST_Qt5 AND CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5AutoMocDeps-build)
- set(RunCMake_TEST_OPTIONS "-DQt5Core_DIR=${Qt5Core_DIR}" "-DQt5Widgets_DIR=${Qt5Widgets_DIR}")
- run_cmake(Qt5AutoMocDeps)
- unset(RunCMake_TEST_OPTIONS)
+function(run_QtAutoMocDeps)
+ set(QtX Qt${CMake_TEST_Qt_version})
+ if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocDeps-build)
+ run_cmake_with_options(QtAutoMocDeps
+ "-Dwith_qt_version=${CMake_TEST_Qt_version}"
+ "-D${QtX}_DIR=${${QtX}_DIR}"
+ "-D${QtX}Core_DIR=${${QtX}Core_DIR}"
+ "-D${QtX}Widgets_DIR=${${QtX}Widgets_DIR}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
+ )
# Build the project.
run_ninja("${RunCMake_TEST_BINARY_DIR}")
# Touch just the library source file, which shouldn't cause a rerun of AUTOMOC
@@ -352,4 +357,6 @@ function(run_Qt5AutoMocDeps)
run_ninja("${RunCMake_TEST_BINARY_DIR}")
endif()
endfunction()
-run_Qt5AutoMocDeps()
+if(CMake_TEST_Qt_version)
+ run_QtAutoMocDeps()
+endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt
new file mode 100644
index 000000000..80e9c2ff9
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-in-release-graph-ninja-stdout.txt
@@ -0,0 +1,2 @@
+^\[1/1\] Generating echo_depend_target\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt
new file mode 100644
index 000000000..1a7987786
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-debug-ninja-stdout.txt
@@ -0,0 +1,2 @@
+^\[1/1\] Generating echo_depend_target\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Debug[\/]echo(\.exe)?' 'Debug'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt
new file mode 100644
index 000000000..80e9c2ff9
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex-echo_depend_target-release-ninja-stdout.txt
@@ -0,0 +1,2 @@
+^\[1/1\] Generating echo_depend_target\.txt
+'[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build'\$ '[^']*[\/]Tests[\/]RunCMake[\/]NinjaMultiConfig[\/]CustomCommandOutputGenex-build[\/]Release[\/]echo(\.exe)?' 'Release'$
diff --git a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake
index bb68a509e..2de5a3a77 100644
--- a/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/CustomCommandOutputGenex.cmake
@@ -143,6 +143,16 @@ add_custom_command(
PROPERTY SYMBOLIC 1)
add_custom_target(echo_dbgx DEPENDS "$<$<CONFIG:Debug>:echo_dbgx_Debug.txt>")
+# A non-cross-config custom command expresses target dependencies in command config.
+add_custom_command(
+ OUTPUT echo_depend_target.txt
+ COMMAND ${CMAKE_COMMAND} -E env $<TARGET_FILE:echo> $<CONFIG>
+ # A real project should do:
+ # DEPENDS $<TARGET_FILE:echo>
+ # but here we are testing the target-level dependency implied by TARGET_FILE.
+ )
+add_custom_target(echo_depend_target DEPENDS echo_depend_target.txt)
+
add_custom_target(echo_target_raw
BYPRODUCTS echo_target_raw_$<CONFIG>.txt
COMMENT echo_target_raw
diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-automoc-check-ninja-stdout.txt b/Tests/RunCMake/NinjaMultiConfig/QtX-automoc-check-ninja-stdout.txt
index 85d5fdc75..85d5fdc75 100644
--- a/Tests/RunCMake/NinjaMultiConfig/Qt5-automoc-check-ninja-stdout.txt
+++ b/Tests/RunCMake/NinjaMultiConfig/QtX-automoc-check-ninja-stdout.txt
diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake
index 2d8df133a..2d8df133a 100644
--- a/Tests/RunCMake/NinjaMultiConfig/Qt5-debug-in-release-graph-build-check.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/QtX-debug-in-release-graph-build-check.cmake
diff --git a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake
index 578256a73..130f88390 100644
--- a/Tests/RunCMake/NinjaMultiConfig/Qt5.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/QtX.cmake
@@ -1,18 +1,21 @@
enable_language(CXX)
-find_package(Qt5Core REQUIRED)
+set(QtX Qt${with_qt_version})
+
+find_package(${QtX} REQUIRED COMPONENTS Core)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOMOC_COMPILER_PREDEFINES OFF)
+# Source files are always named qt5.* for simplicity but apply to Qt5 and later
add_executable(exe qt5.cxx)
-target_link_libraries(exe PRIVATE Qt5::Core)
+target_link_libraries(exe PRIVATE ${QtX}::Core)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(exe)
set(moc_writes_depfiles 0)
-if(Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
+if(${QtX}Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
set(moc_writes_depfiles 1)
endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index 7c100eb1e..4a0c130a1 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -344,6 +344,16 @@ run_ninja(CustomCommandOutputGenex echo_dbgx-release build-Release.ninja echo_db
run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
run_ninja(CustomCommandOutputGenex echo_dbgx-debug-in-release-graph build-Release.ninja echo_dbgx:Debug)
run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+# echo_depend_target
+run_ninja(CustomCommandOutputGenex echo_depend_target-debug-prep build-Debug.ninja echo:Debug)
+run_ninja(CustomCommandOutputGenex echo_depend_target-debug build-Debug.ninja echo_depend_target)
+run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_depend_target-release-prep build-Release.ninja echo:Release)
+run_ninja(CustomCommandOutputGenex echo_depend_target-release build-Release.ninja echo_depend_target)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
+run_ninja(CustomCommandOutputGenex echo_depend_target-debug-in-release-graph-prep build-Release.ninja echo:Release)
+run_ninja(CustomCommandOutputGenex echo_depend_target-debug-in-release-graph build-Release.ninja echo_depend_target:Debug)
+run_ninja(CustomCommandOutputGenex clean-release-graph build-Release.ninja -t clean)
# echo_target_raw
run_ninja(CustomCommandOutputGenex echo_target_raw-debug build-Debug.ninja echo_target_raw:Debug)
run_ninja(CustomCommandOutputGenex clean-debug-graph build-Debug.ninja -t clean)
@@ -446,14 +456,20 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang")
run_ninja(CudaSimple all-clean build-Debug.ninja clean:Debug)
endif()
-if(CMake_TEST_Qt5)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5-build)
- set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all" "-DQt5Core_DIR=${Qt5Core_DIR}")
- run_cmake_configure(Qt5)
+if(CMake_TEST_Qt_version)
+ set(QtX Qt${CMake_TEST_Qt_version})
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtX-build)
+ set(RunCMake_TEST_OPTIONS
+ "-DCMAKE_CROSS_CONFIGS=all"
+ "-Dwith_qt_version:STRING=${CMake_TEST_Qt_version}"
+ "-D${QtX}Core_DIR=${${QtX}Core_DIR}"
+ "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
+ )
+ run_cmake_configure(QtX)
unset(RunCMake_TEST_OPTIONS)
include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
- run_cmake_build(Qt5 debug-in-release-graph Release exe:Debug)
- if(CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0)
- run_ninja(Qt5 automoc-check build-Debug.ninja -t query exe_autogen/timestamp)
+ run_cmake_build(QtX debug-in-release-graph Release exe:Debug)
+ if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0)
+ run_ninja(QtX automoc-check build-Debug.ninja -t query exe_autogen/timestamp)
endif()
endif()
diff --git a/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
new file mode 100644
index 000000000..a4554103d
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.15)
+project(PchIncludedAllLanguages C CXX)
+
+if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH)
+ add_definitions(-DHAVE_PCH_SUPPORT)
+endif()
+
+add_executable(main
+ main.cpp
+ pch-included.c
+ pch-included.cpp
+)
+target_precompile_headers(main PRIVATE pch.h)
+
+enable_testing()
+add_test(NAME main COMMAND main)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake
new file mode 100644
index 000000000..b4fdb712a
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchLibObjLibExe.cmake
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.16)
+project(PchLibObjLibExe CXX)
+
+foreach(i 1 2 3)
+ file(WRITE ${CMAKE_BINARY_DIR}/empty${i}.cpp "void nothing${i}() {}\n")
+endforeach()
+
+add_library(base_lib_static STATIC ${CMAKE_BINARY_DIR}/empty1.cpp)
+target_precompile_headers(base_lib_static PRIVATE <vector>)
+
+add_library(object_lib OBJECT ${CMAKE_BINARY_DIR}/empty2.cpp)
+target_precompile_headers(object_lib REUSE_FROM base_lib_static)
+
+add_library(mid_lib_static STATIC ${CMAKE_BINARY_DIR}/empty3.cpp)
+target_link_libraries(mid_lib_static PRIVATE object_lib)
+
+add_executable(exec main.cpp)
+target_link_libraries(exec PRIVATE mid_lib_static)
+set_target_properties(exec PROPERTIES MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>)
+
+target_precompile_headers(exec PRIVATE <string>)
+
+enable_testing()
+add_test(NAME exec COMMAND exec)
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index 8cc59d224..ca5b52e87 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -28,3 +28,5 @@ if(RunCMake_GENERATOR MATCHES "Make|Ninja")
endif()
endif()
run_test(PchReuseFromObjLib)
+run_test(PchIncludedAllLanguages)
+run_test(PchLibObjLibExe)
diff --git a/Tests/RunCMake/PrecompileHeaders/pch-included.c b/Tests/RunCMake/PrecompileHeaders/pch-included.c
new file mode 100644
index 000000000..96fce697e
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/pch-included.c
@@ -0,0 +1,8 @@
+#ifndef HAVE_PCH_SUPPORT
+# include "pch.h"
+#endif
+
+int testC(void)
+{
+ return PCH_INCLUDED;
+}
diff --git a/Tests/RunCMake/PrecompileHeaders/pch-included.cpp b/Tests/RunCMake/PrecompileHeaders/pch-included.cpp
new file mode 100644
index 000000000..bf4d95d47
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/pch-included.cpp
@@ -0,0 +1,8 @@
+#ifndef HAVE_PCH_SUPPORT
+# include "pch.h"
+#endif
+
+int testCpp()
+{
+ return PCH_INCLUDED;
+}
diff --git a/Tests/RunCMake/PrecompileHeaders/pch.h b/Tests/RunCMake/PrecompileHeaders/pch.h
index 81b6d9eed..20672d1f8 100644
--- a/Tests/RunCMake/PrecompileHeaders/pch.h
+++ b/Tests/RunCMake/PrecompileHeaders/pch.h
@@ -1,3 +1,5 @@
#pragma once
#define PCH_INCLUDED 1
+
+int testC(void);
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 02e0decbb..3363a579e 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -156,9 +156,8 @@ function(run_cmake test)
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
"|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
- "|[^\n]*xcodebuild[^\n]*Requested but did not find extension point with identifier"
"|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
- "|[^\n]*objc[^\n]*: Class [^\n]* One of the two will be used. Which one is undefined."
+ "|[^\n]*objc[^\n]*: Class AMSupportURL[^\n]* One of the two will be used. Which one is undefined."
"|[^\n]*is a member of multiple groups"
"|[^\n]*offset in archive not a multiple of 8"
"|[^\n]*from Time Machine by path"
diff --git a/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt
new file mode 100644
index 000000000..fca7a73a4
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0086-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0086 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index e11a24a96..d5ed136ac 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -41,7 +41,6 @@ run_cmake(VsDeployEnabled)
run_cmake(VsSettings)
run_cmake(VsSourceSettingsTool)
run_cmake(VsPlatformToolset)
-run_cmake(VsControlFlowGuardLinkSetting)
run_cmake(VsWinRTByDefault)
diff --git a/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting-check.cmake b/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting-check.cmake
deleted file mode 100644
index c13858bd9..000000000
--- a/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting-check.cmake
+++ /dev/null
@@ -1,40 +0,0 @@
-set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/ControlFlowGuardProject.vcxproj")
-if(NOT EXISTS "${vcProjectFile}")
- set(RunCMake_TEST_FAILED "Project file ControlFlowGuardProject.vcxproj does not exist.")
- return()
-endif()
-
-set(Is_in_link_section 0)
-set(HAS_ControlFlowGuardSetting 0)
-
-file(STRINGS "${vcProjectFile}" lines)
-foreach(line IN LISTS lines)
- if(line MATCHES "^ *<LinkControlFlowGuard>([^<>]+)</LinkControlFlowGuard>")
- set(RunCMake_TEST_FAILED "Project file ControlFlowGuardProject.vcxproj contains the invalid <LinkControlFlowGuard> link property.")
- return()
- break()
- endif()
- if(line MATCHES "^ *<Link>")
- # The start of the link section of the vcxproj file
- set(Is_in_link_section 1)
- continue()
- endif()
- if(line MATCHES "^ *</Link>")
- # The end of the link section of the vcxproj file
- set(Is_in_link_section 0)
- continue()
- endif()
- if(Is_in_link_section)
- if(line MATCHES "^ *<AdditionalOptions>([^<>]+)</AdditionalOptions>")
- if("${CMAKE_MATCH_1}" MATCHES ".*/guard:cf.*")
- set(HAS_ControlFlowGuardSetting 1)
- break()
- endif()
- endif()
- endif()
-endforeach()
-
-if(NOT HAS_ControlFlowGuardSetting)
- set(RunCMake_TEST_FAILED "Project file ControlFlowGuardProject.vcxproj does not have '/guard:cf' specified in the <AdditionalOptions> property.")
- return()
-endif()
diff --git a/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting.cmake b/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting.cmake
deleted file mode 100644
index 31e69acd3..000000000
--- a/Tests/RunCMake/VS10Project/VsControlFlowGuardLinkSetting.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-enable_language(CXX)
-
-# Add the Control Flow Guard compiler and linker option
-add_compile_options("/guard:cf")
-string(APPEND CMAKE_SHARED_LINKER_FLAGS " /guard:cf")
-
-add_library(ControlFlowGuardProject SHARED foo.cpp)
diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
index 95fc5caec..39415afa3 100644
--- a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
+++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
@@ -1,3 +1,3 @@
-CMake Error: Bad parameter for VS_DPI_AWARE: Bar
CMake Error: Bad parameter for VS_DPI_AWARE: Foo
+CMake Error: Bad parameter for VS_DPI_AWARE: Bar
CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/VS10Project/VsSettings-check.cmake b/Tests/RunCMake/VS10Project/VsSettings-check.cmake
index 0f8b26c28..13cc8e25a 100644
--- a/Tests/RunCMake/VS10Project/VsSettings-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsSettings-check.cmake
@@ -4,20 +4,29 @@ macro(ensure_props_set projectFile)
return()
endif()
- set(SettingFound FALSE)
+ set(Setting1Found FALSE)
+ set(Setting2Found FALSE)
file(STRINGS "${projectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "<SourceProperty1.*Debug.*>SourceProperty1Value</SourceProperty1>")
message("SourceProperty1 setting found")
- set(SettingFound TRUE)
+ set(Setting1Found TRUE)
+ endif()
+ if(line MATCHES "<SourceProperty2.*Debug.*>SourceProperty2Value</SourceProperty2>")
+ message("SourceProperty2 setting found")
+ set(Setting2Found TRUE)
endif()
endforeach()
- if (NOT SettingFound)
+ if (NOT Setting1Found)
set(RunCMake_TEST_FAILED "SourceProperty1 setting was not found")
return()
endif()
+ if (NOT Setting2Found)
+ set(RunCMake_TEST_FAILED "SourceProperty2 setting was not found")
+ return()
+ endif()
endmacro()
ensure_props_set("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
diff --git a/Tests/RunCMake/VS10Project/VsSettings.cmake b/Tests/RunCMake/VS10Project/VsSettings.cmake
index a4b321b65..3a046f164 100644
--- a/Tests/RunCMake/VS10Project/VsSettings.cmake
+++ b/Tests/RunCMake/VS10Project/VsSettings.cmake
@@ -3,3 +3,5 @@ enable_language(CXX)
add_library(foo foo.cpp shader.hlsl)
set_property(SOURCE shader.hlsl PROPERTY VS_SETTINGS
"$<$<CONFIG:DEBUG>:SourceProperty1=SourceProperty1Value>")
+set_property(SOURCE foo.cpp PROPERTY VS_SETTINGS
+ "$<$<CONFIG:DEBUG>:SourceProperty2=SourceProperty2Value>")
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake
index f4fe07fde..54375d52b 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOff.cmake
@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
- XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY OFF
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY OFF
)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake
index e4ea55df2..23fd49d59 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir-build-check.cmake
@@ -1,3 +1,3 @@
-if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/sharedFrameworkExt.framework)
- set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
+if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/${EXTERNAL_DEPENDENCY_NAME})
+ set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location")
endif()
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake
index 79d8d7779..c76226fb9 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnNoSubdir.cmake
@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
- XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
)
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake
index 57c79eae4..732f04c23 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir-build-check.cmake
@@ -1,3 +1,3 @@
-if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/sharedFrameworkExt.framework)
- set(RunCMake_TEST_FAILED "Framework was not embedded at the expected location")
+if(NOT EXISTS ${RunCMake_TEST_BINARY_DIR}/Debug/app.app/Contents/Frameworks/subdir/${EXTERNAL_DEPENDENCY_NAME})
+ set(RunCMake_TEST_FAILED "${EXTERNAL_DEPENDENCY_NAME} was not embedded at the expected location")
endif()
diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake
index 4c78199e5..f83b1bf79 100644
--- a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksFlagsOnWithSubdir.cmake
@@ -1,7 +1,7 @@
add_executable(app MACOSX_BUNDLE main.m)
set_target_properties(app PROPERTIES
- XCODE_EMBED_FRAMEWORKS "${EXTERNAL_FWK}"
+ XCODE_EMBED_FRAMEWORKS "${EXTERNAL_DEPENDENCY}"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
XCODE_EMBED_FRAMEWORKS_PATH "subdir"
diff --git a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake
index 64e2f9587..8c7b06af9 100644
--- a/Tests/RunCMake/XcodeProject-Embed/ExternalFramework.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/ExternalDependencies.cmake
@@ -1,2 +1,4 @@
add_library(sharedFrameworkExt SHARED func.m)
set_target_properties(sharedFrameworkExt PROPERTIES FRAMEWORK TRUE)
+
+add_library(sharedDylibExt SHARED func.m)
diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
index e94d084c1..f3a691872 100644
--- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake
@@ -1,47 +1,49 @@
include(RunCMake)
-# Build a framework that the other tests will use and treat as external.
+# Build dependencies that the other tests will use and treat as external.
# Always build in the Debug configuration so that the path to the framework
# is predictable.
-function(ExternalFramework)
+function(ExternalDependencies)
set(RunCMake_TEST_NO_CLEAN 1)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalFramework-build)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExternalDependencies-build)
set(externalFramework ${RunCMake_TEST_BINARY_DIR}/Debug/sharedFrameworkExt.framework PARENT_SCOPE)
+ set(externalDylib ${RunCMake_TEST_BINARY_DIR}/Debug/libsharedDylibExt.dylib PARENT_SCOPE)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
- run_cmake(ExternalFramework)
- run_cmake_command(ExternalFramework-build
+ run_cmake(ExternalDependencies)
+ run_cmake_command(ExternalDependencies-build
${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
--config Debug
- --target sharedFrameworkExt
+ --target sharedFrameworkExt sharedDylibExt
)
endfunction()
-ExternalFramework()
+ExternalDependencies()
-set(RunCMake_TEST_OPTIONS -DEXTERNAL_FWK=${externalFramework})
-
-run_cmake(EmbedFrameworksFlagsOff)
-
-function(TestFlagsOn testName)
+function(TestFlagsOn testName dependencyName)
set(RunCMake_TEST_NO_CLEAN 1)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-build)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${testName}-${dependencyName}-build)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(${testName})
- run_cmake_command(${testName}-build
+ run_cmake_command(${testName}-${dependencyName}-build
${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}
--config Debug
--target app
)
endfunction()
-TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir)
-TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir)
-
+foreach(dependency ${externalFramework} ${externalDylib})
+ cmake_path(GET dependency FILENAME dependencyName)
+ set(RunCMake_TEST_OPTIONS -DEXTERNAL_DEPENDENCY=${dependency} -DEXTERNAL_DEPENDENCY_NAME=${dependencyName})
+ run_cmake(EmbedFrameworksFlagsOff)
+ TestFlagsOn(EmbedFrameworksFlagsOnNoSubdir ${dependencyName})
+ TestFlagsOn(EmbedFrameworksFlagsOnWithSubdir ${dependencyName})
+endforeach()
+unset(RunCMake_TEST_OPTIONS)
function(TestAppExtension platform)
set(testName EmbedAppExtensions-${platform})
diff --git a/Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt
new file mode 100644
index 000000000..50838c38f
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/CMP0082-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning at CMakeLists.txt:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0082 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.$
diff --git a/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake
new file mode 100644
index 000000000..ad873eb29
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake
@@ -0,0 +1 @@
+message(WARNING "The warning text to match just to make sure the script get executed")
diff --git a/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake
new file mode 100644
index 000000000..08d8da80d
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake
@@ -0,0 +1,21 @@
+if(DEFINED CMAKE_GET_OS_RELEASE_FALLBACK_RESULT)
+ message(FATAL_ERROR "The `CMAKE_GET_OS_RELEASE_FALLBACK_RESULT` expected to be unset at this moment")
+endif()
+
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME UnitTest)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "Just a Unit Test")
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID unittest)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE nothing)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION 0.0.1)
+set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID 0.0.1)
+
+list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ IGNORED_VARIABLE_NAME_WHICH_IS_NOT_STARTED_WITH_EXPECTED_PREFIX
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ )
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt
new file mode 100644
index 000000000..ed995e6a6
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg1\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information missing RESULT specification.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake
index 1655eb406..1655eb406 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt
new file mode 100644
index 000000000..b78c927f1
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg2\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information missing QUERY specification
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake
index 1f056d5f2..1f056d5f2 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt
new file mode 100644
index 000000000..c3f13140a
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadArg3\.cmake:1 \(cmake_host_system_information\):
+ cmake_host_system_information does not recognize <key> FOOBAR
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:7 \(include\)
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake
index 9c5a558c7..9c5a558c7 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake
diff --git a/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt
new file mode 100644
index 000000000..0198f9be0
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.21)
+
+project(${RunCMake_TEST} NONE)
+
+set(CMAKE_SYSROOT ${PROJECT_SOURCE_DIR}/${RunCMake_TEST})
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt
new file mode 100644
index 000000000..50dbb0876
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt
@@ -0,0 +1,7 @@
+-- CENTOS6_ID=`centos`
+-- CENTOS6_ID_LIKE=`rhel`
+-- CENTOS6_NAME=`CentOS`
+-- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)`
+-- CENTOS6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/010-TryOldCentOS.cmake`
+-- CENTOS6_VERSION=`6\.10`
+-- CENTOS6_VERSION_ID=`6\.10`
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake
new file mode 100644
index 000000000..3bc632b9b
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS CENTOS6)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release
new file mode 100644
index 000000000..294ccc9f8
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release
@@ -0,0 +1 @@
+CentOS release 6.10 (Final)
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt
new file mode 100644
index 000000000..4193d6f5e
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt
@@ -0,0 +1,5 @@
+-- DEBIAN6_ID=`debian`
+-- DEBIAN6_NAME=`Debian`
+-- DEBIAN6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/020-TryDebianVersion.cmake`
+-- DEBIAN6_VERSION=`6\.0\.10`
+-- DEBIAN6_VERSION_ID=`6\.0\.10`
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake
new file mode 100644
index 000000000..cbf83a9f1
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS DEBIAN6)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version
new file mode 100644
index 000000000..c7d48f048
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version
@@ -0,0 +1 @@
+6.0.10
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt
new file mode 100644
index 000000000..11ae71f42
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt
@@ -0,0 +1,9 @@
+-- TEST1_ANSI_COLOR=`0;32`
+-- TEST1_BUG_REPORT_URL=`https://bugs.exherbo.org/`
+-- TEST1_HOME_URL=`https://www.exherbo.org/`
+-- TEST1_ID=`exherbo`
+-- TEST1_NAME=`Exherbo`
+-- TEST1_PRETTY_NAME=`Exherbo Linux`
+-- TEST1_SUPPORT_URL=`irc://irc.freenode.net/#exherbo`
+-- TEST2_ID=`exherbo`
+-- TEST2_VERSION=``
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake
new file mode 100644
index 000000000..7fc26d812
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake
@@ -0,0 +1,11 @@
+cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS TEST1)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
+
+# Query individual variables
+cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION)
+list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION)
+message(STATUS "TEST2_ID=`${TEST2_ID}`")
+message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`")
diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release
new file mode 100644
index 000000000..944c9b44e
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release
@@ -0,0 +1,7 @@
+NAME="Exherbo"
+PRETTY_NAME="Exherbo Linux"
+ID="exherbo"
+ANSI_COLOR="0;32"
+HOME_URL="https://www.exherbo.org/"
+SUPPORT_URL="irc://irc.freenode.net/#exherbo"
+BUG_REPORT_URL="https://bugs.exherbo.org/"
diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt
new file mode 100644
index 000000000..f583deb62
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt
@@ -0,0 +1,27 @@
+-- NUMBER_OF_LOGICAL_CORES=`[0-9]+`
+-- NUMBER_OF_PHYSICAL_CORES=`[0-9]+`
+-- HOSTNAME=`.*`
+-- FQDN=`.*`
+-- TOTAL_VIRTUAL_MEMORY=`[0-9]+`
+-- AVAILABLE_VIRTUAL_MEMORY=`[0-9]+`
+-- TOTAL_PHYSICAL_MEMORY=`[0-9]+`
+-- AVAILABLE_PHYSICAL_MEMORY=`[0-9]+`
+-- IS_64BIT=`[01]`
+-- HAS_FPU=`[01]`
+-- HAS_MMX=`[01]`
+-- HAS_MMX_PLUS=`[01]`
+-- HAS_SSE=`[01]`
+-- HAS_SSE2=`[01]`
+-- HAS_SSE_FP=`[01]`
+-- HAS_SSE_MMX=`[01]`
+-- HAS_AMD_3DNOW=`[01]`
+-- HAS_AMD_3DNOW_PLUS=`[01]`
+-- HAS_IA64=`[01]`
+-- HAS_SERIAL_NUMBER=`[01]`
+-- PROCESSOR_SERIAL_NUMBER=`.*`
+-- PROCESSOR_NAME=`.*`
+-- PROCESSOR_DESCRIPTION=`.*`
+-- OS_NAME=`.*`
+-- OS_RELEASE=`.*`
+-- OS_VERSION=`.*`
+-- OS_PLATFORM=`.*`
diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake
index a3c2b055a..f22a0ae70 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in
+++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake
@@ -1,19 +1,8 @@
-set(BadArg1-RESULT 1)
-set(BadArg1-STDERR "missing RESULT specification")
-set(BadArg2-RESULT 1)
-set(BadArg2-STDERR "missing QUERY specification")
-set(BadArg3-RESULT 1)
-set(BadArg3-STDERR "does not recognize <key> FOOBAR")
-set(QueryList-RESULT 0)
-set(QueryList-STDERR "\\[[0-9]+;[0-9]+\\]")
-
function(try_and_print key)
- cmake_host_system_information(RESULT RESULT QUERY ${key})
- message(STATUS "[${key}] [${RESULT}]")
+ cmake_host_system_information(RESULT RESULT QUERY ${key})
+ message(STATUS "${key}=`${RESULT}`")
endfunction()
-message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
-
try_and_print(NUMBER_OF_LOGICAL_CORES)
try_and_print(NUMBER_OF_PHYSICAL_CORES)
try_and_print(HOSTNAME)
@@ -41,12 +30,3 @@ try_and_print(OS_NAME)
try_and_print(OS_RELEASE)
try_and_print(OS_VERSION)
try_and_print(OS_PLATFORM)
-
-include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake")
-
-check_cmake_test(CMakeHostSystemInformation
- BadArg1
- BadArg2
- BadArg3
- QueryList
-)
diff --git a/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt
new file mode 100644
index 000000000..eebe0d40e
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt
@@ -0,0 +1 @@
+-- \[[0-9]+;[0-9]+\]
diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake
index 1c3156d23..f24aa2bdf 100644
--- a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake
+++ b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake
@@ -2,4 +2,4 @@ cmake_host_system_information(RESULT RESULT
QUERY NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES
)
-message("[${RESULT}]")
+message(STATUS "[${RESULT}]")
diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
new file mode 100644
index 000000000..87b6944dc
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
@@ -0,0 +1,23 @@
+include(RunCMake)
+
+run_cmake(BadArg1)
+run_cmake(BadArg2)
+run_cmake(BadArg3)
+
+run_cmake(QueryList)
+run_cmake(QueryKeys)
+
+run_cmake(UnitTest)
+run_cmake(Exherbo)
+run_cmake(Ubuntu)
+
+run_cmake(CentOS6)
+run_cmake(Debian6)
+
+run_cmake(UserFallbackScript)
+
+if(RunCMake_GENERATOR MATCHES "^Visual Studio " AND NOT RunCMake_GENERATOR STREQUAL "Visual Studio 9 2008")
+ run_cmake(VsMSBuild)
+else()
+ run_cmake(VsMSBuildMissing)
+endif()
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt
new file mode 100644
index 000000000..d1a18da23
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt
@@ -0,0 +1,14 @@
+-- TEST1_BUG_REPORT_URL=`https://bugs\.launchpad\.net/ubuntu/`
+-- TEST1_HOME_URL=`https://www\.ubuntu\.com/`
+-- TEST1_ID=`ubuntu`
+-- TEST1_ID_LIKE=`debian`
+-- TEST1_NAME=`Ubuntu`
+-- TEST1_PRETTY_NAME=`Ubuntu 20\.04\.2 LTS`
+-- TEST1_PRIVACY_POLICY_URL=`https://www\.ubuntu\.com/legal/terms-and-policies/privacy-policy`
+-- TEST1_SUPPORT_URL=`https://help\.ubuntu\.com/`
+-- TEST1_UBUNTU_CODENAME=`focal`
+-- TEST1_VERSION=`20\.04\.2 LTS \(Focal Fossa\)`
+-- TEST1_VERSION_CODENAME=`focal`
+-- TEST1_VERSION_ID=`20\.04`
+-- TEST2_ID=`ubuntu`
+-- TEST2_VERSION=`20\.04\.2 LTS \(Focal Fossa\)`
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake
new file mode 100644
index 000000000..7fc26d812
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake
@@ -0,0 +1,11 @@
+cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS TEST1)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
+
+# Query individual variables
+cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION)
+list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION)
+message(STATUS "TEST2_ID=`${TEST2_ID}`")
+message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`")
diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release
new file mode 100644
index 000000000..f228f2226
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release
@@ -0,0 +1,12 @@
+NAME="Ubuntu"
+VERSION="20.04.2 LTS (Focal Fossa)"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu 20.04.2 LTS"
+VERSION_ID="20.04"
+HOME_URL="https://www.ubuntu.com/"
+SUPPORT_URL="https://help.ubuntu.com/"
+BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
+PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
+VERSION_CODENAME=focal
+UBUNTU_CODENAME=focal
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt
new file mode 100644
index 000000000..db6f48760
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt
@@ -0,0 +1,7 @@
+-- UNIT_TEST_A_LIST_LIKE_VARIABLE=`satu;dua;tiga`
+-- UNIT_TEST_DBL_QUOTED_VALUE=`"The" value in double "quotes"`
+-- UNIT_TEST_DBL_QUOTED_VALUE_STIPPED_COMMENT=`Blah blah blah`
+-- UNIT_TEST_NON_SPACE_VALUE=`Blah-blah-blah`
+-- UNIT_TEST_QUOTED_VALUE=`'The' value in single 'quotes'`
+-- UNIT_TEST_QUOTED_VALUE_STIPPED_COMMENT=`The value in single quotes`
+-- UNIT_TEST_THE_URL_WITH_ANCHOR_TEST=`https://blah.blah/resource#anchor`
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake
new file mode 100644
index 000000000..d9a0acae8
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake
@@ -0,0 +1,5 @@
+cmake_host_system_information(RESULT UNIT_TEST QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS UNIT_TEST)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release
new file mode 100644
index 000000000..66c33b599
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release
@@ -0,0 +1,9 @@
+# Comment string gonna be ignored
+NON_SPACE_VALUE=Blah-blah-blah
+QUOTED_VALUE='\'The\' value in single \'quotes\''
+QUOTED_VALUE_STIPPED_COMMENT='The value in single quotes'# The comment right after `'`
+DBL_QUOTED_VALUE="\"The\" value in double \"quotes\""
+DBL_QUOTED_VALUE_STIPPED_COMMENT="Blah blah blah"# The comment right after `'`
+THE_URL_WITH_ANCHOR_TEST="https://blah.blah/resource#anchor" # And a comment after
+A_LIST_LIKE_VARIABLE='satu;dua;tiga'
+INCORRECT_ESCAPE_IGNORED=\'This line gonna be ignored'
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt
new file mode 100644
index 000000000..78acea2b4
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt
@@ -0,0 +1,5 @@
+CMake Warning at 000-FirstFallbackScript\.cmake:[0-9]+ \(message\):
+ The warning text to match just to make sure the script get executed
+Call Stack \(most recent call first\):
+ UserFallbackScript\.cmake:[0-9]+ \(cmake_host_system_information\)
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt
new file mode 100644
index 000000000..acaf47e69
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt
@@ -0,0 +1,7 @@
+-- UFS_ID=`unittest`
+-- UFS_ID_LIKE=`nothing`
+-- UFS_NAME=`UnitTest`
+-- UFS_PRETTY_NAME=`Just a Unit Test`
+-- UFS_USED_FALLBACK_SCRIPT=`.*/999-LastFallbackScript\.cmake`
+-- UFS_VERSION=`0\.0\.1`
+-- UFS_VERSION_ID=`0\.0\.1`
diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake
new file mode 100644
index 000000000..660aa1ca3
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake
@@ -0,0 +1,12 @@
+list(
+ APPEND CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS
+ ${CMAKE_CURRENT_SOURCE_DIR}/000-FirstFallbackScript.cmake
+ ${CMAKE_CURRENT_SOURCE_DIR}/Ignored-Script.cmake
+ ${CMAKE_CURRENT_SOURCE_DIR}/999-LastFallbackScript.cmake
+ )
+
+cmake_host_system_information(RESULT UFS QUERY DISTRIB_INFO)
+
+foreach(VAR IN LISTS UFS)
+ message(STATUS "${VAR}=`${${VAR}}`")
+endforeach()
diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake b/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake
new file mode 100644
index 000000000..30e616eb0
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuild.cmake
@@ -0,0 +1,4 @@
+cmake_host_system_information(RESULT msbuild QUERY VS_MSBUILD_COMMAND)
+if(NOT EXISTS "${msbuild}")
+ message(FATAL_ERROR "VS_MSBUILD_COMMAND returned path that does not exist:\n ${msbuild}")
+endif()
diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt
new file mode 100644
index 000000000..3a7dfef6d
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at VsMSBuildMissing.cmake:[0-9]+ \(cmake_host_system_information\):
+ cmake_host_system_information does not recognize <key> VS_MSBUILD_COMMAND
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake
new file mode 100644
index 000000000..23c036429
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/VsMSBuildMissing.cmake
@@ -0,0 +1 @@
+cmake_host_system_information(RESULT msbuild QUERY VS_MSBUILD_COMMAND)
diff --git a/Tests/RunCMake/ctest_environment/CMakeLists.txt.in b/Tests/RunCMake/ctest_environment/CMakeLists.txt.in
new file mode 100644
index 000000000..c9c4a645e
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.21.0)
+project("@CASE_NAME@" NONE)
+include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt
new file mode 100644
index 000000000..b57e2deb7
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt
new file mode 100644
index 000000000..5b56d6fb0
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op-stderr.txt
@@ -0,0 +1 @@
+Error: Unrecognized environment manipulation argument: unknown
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake
new file mode 100644
index 000000000..d6ca4b2ee
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-invalid-op.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version)
+
+set_property(TEST cmake_version
+ PROPERTY ENVIRONMENT_MODIFICATION
+ INVALID_OP=unknown:)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt
new file mode 100644
index 000000000..b57e2deb7
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt
new file mode 100644
index 000000000..3ba6ba7b1
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon-stderr.txt
@@ -0,0 +1 @@
+Error: Missing `:` after the operation in: MISSING_COLON=unset
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake
new file mode 100644
index 000000000..601dd8b40
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-colon.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+
+add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version)
+set_property(TEST cmake_version
+ PROPERTY ENVIRONMENT_MODIFICATION
+ MISSING_COLON=unset)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt
new file mode 100644
index 000000000..b57e2deb7
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt
new file mode 100644
index 000000000..20bc9a599
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals-stderr.txt
@@ -0,0 +1 @@
+Error: Missing `=` after the variable name in: MISSING_EQUAL
diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake
new file mode 100644
index 000000000..18448cf41
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-no-equals.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+
+add_test(NAME cmake_version COMMAND "${CMAKE_COMMAND}" --version)
+set_property(TEST cmake_version
+ PROPERTY ENVIRONMENT_MODIFICATION
+ MISSING_EQUAL)
diff --git a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake
new file mode 100644
index 000000000..3447779f3
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake
@@ -0,0 +1,12 @@
+include(RunCTest)
+
+# Isolate our ctest runs from external environment.
+unset(ENV{CTEST_PARALLEL_LEVEL})
+unset(ENV{CTEST_OUTPUT_ON_FAILURE})
+
+set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
+set(RunCTest_VERBOSE_FLAG "-VV")
+
+run_ctest(ENVIRONMENT_MODIFICATION-invalid-op)
+run_ctest(ENVIRONMENT_MODIFICATION-no-colon)
+run_ctest(ENVIRONMENT_MODIFICATION-no-equals)
diff --git a/Tests/RunCMake/ctest_environment/test.cmake.in b/Tests/RunCMake/ctest_environment/test.cmake.in
new file mode 100644
index 000000000..ca23c832f
--- /dev/null
+++ b/Tests/RunCMake/ctest_environment/test.cmake.in
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.7)
+
+set(CTEST_SITE "test-site")
+set(CTEST_BUILD_NAME "test-build-name")
+set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+
+set(ctest_test_args "@CASE_CTEST_TEST_ARGS@")
+ctest_start(Experimental)
+ctest_configure()
+ctest_build()
+ctest_test(${ctest_test_args})
diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake
new file mode 100644
index 000000000..9d2a059a4
--- /dev/null
+++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake
@@ -0,0 +1,10 @@
+function (find_xml_file name)
+ file(GLOB test_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${name}.xml")
+ if (NOT test_xml_file)
+ message(FATAL_ERROR
+ "${name}.xml not created.")
+ endif ()
+endfunction ()
+
+find_xml_file(DynamicAnalysis)
+find_xml_file(DynamicAnalysis-Test)
diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt
new file mode 100644
index 000000000..e1fc77a22
--- /dev/null
+++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt
@@ -0,0 +1 @@
+Cannot find memory tester output file: .*/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-build/Testing/Temporary/MemoryChecker.1.log\.\*
diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt
new file mode 100644
index 000000000..b3473bfd9
--- /dev/null
+++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt
@@ -0,0 +1,2 @@
+Memory checking results:
+left shift of negative value -256 - 1
diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake
index 6e0a91c85..cb8f6963c 100644
--- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake
@@ -95,6 +95,19 @@ unset(CMAKELISTS_EXTRA_CODE)
unset(CTEST_EXTRA_CODE)
#-----------------------------------------------------------------------------
+# add output test
+set(CTEST_EXTRA_CODE
+"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1\")
+")
+set(CMAKELISTS_EXTRA_CODE
+"add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\"
+-P \"${RunCMake_SOURCE_DIR}/testUndefinedBehaviorSanitizer.cmake\")
+")
+run_mc_test(ExpectedOutputs "" -DMEMCHECK_TYPE=UndefinedBehaviorSanitizer)
+unset(CMAKELISTS_EXTRA_CODE)
+unset(CTEST_EXTRA_CODE)
+
+#-----------------------------------------------------------------------------
set(CTEST_EXTRA_CODE "string(REPLACE \" \" \"\\\\ \" PRE_POST_COMMAND \"\${CTEST_MEMORYCHECK_COMMAND}\")
set(CTEST_CUSTOM_PRE_MEMCHECK \"\${PRE_POST_COMMAND} pre command\")
diff --git a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
index 5f9b32d97..de810499b 100644
--- a/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_test/RunCMakeTest.cmake
@@ -158,13 +158,25 @@ add_test(
COMMAND ${CMAKE_COMMAND} -E
echo <DartMeasurement type="numeric/double" name="my_custom_value">1.4847</DartMeasurement>)
add_test(
+ NAME double_measurement2
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <CTestMeasurement type="numeric/double" name="another_custom_value">1.8474</CTestMeasurement>)
+add_test(
NAME img_measurement
COMMAND ${CMAKE_COMMAND} -E
echo <DartMeasurementFile name="TestImage" type="image/png">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>)
add_test(
+ NAME img_measurement2
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <CTestMeasurementFile name="TestImage2" type="image/png">]] ${IMAGE_DIR}/cmake-logo-16.png [[</CTestMeasurementFile>)
+add_test(
NAME file_measurement
COMMAND ${CMAKE_COMMAND} -E
echo <DartMeasurementFile name="my_test_input_data" type="file">]] ${IMAGE_DIR}/cmake-logo-16.png [[</DartMeasurementFile>)
+add_test(
+ NAME file_measurement2
+ COMMAND ${CMAKE_COMMAND} -E
+ echo <CTestMeasurementFile name="another_test_input_data" type="file">]] ${IMAGE_DIR}/cmake-logo-16.png [[</CTestMeasurementFile>)
]])
run_ctest(TestMeasurements)
endfunction()
@@ -194,3 +206,16 @@ set_property(TEST b PROPERTY LABELS b)
run_ctest(TestChangingLabels)
endfunction()
run_changing_labels()
+
+# Verify that test output can add additional labels
+function(run_extra_labels)
+ set(CASE_CMAKELISTS_SUFFIX_CODE [[
+add_test(
+ NAME custom_labels
+ COMMAND ${CMAKE_COMMAND} -E
+ echo before\n<CTestLabel>label2</CTestLabel>\n<CTestLabel>label1</CTestLabel>\n<CTestLabel>label3</CTestLabel>\n<CTestLabel>label2</CTestLabel>\nafter)
+set_tests_properties(custom_labels PROPERTIES LABELS "label1")
+ ]])
+ run_ctest(TestExtraLabels)
+endfunction()
+run_extra_labels()
diff --git a/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake
new file mode 100644
index 000000000..eaa50d155
--- /dev/null
+++ b/Tests/RunCMake/ctest_test/TestExtraLabels-check.cmake
@@ -0,0 +1,25 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/TAG" _tag)
+string(REGEX REPLACE "^([^\n]*)\n.*$" "\\1" _date "${_tag}")
+file(READ "${RunCMake_TEST_BINARY_DIR}/Testing/${_date}/Test.xml" _test_contents)
+
+# Check labels.
+STRING(REGEX MATCHALL [[<Label>label1</Label>]] matches "${_test_contents}")
+list(LENGTH matches n_matches)
+if(NOT n_matches EQUAL 1)
+ string(APPEND RunCMake_TEST_FAILED "expected 1 match for label1, found ${n_matches}")
+endif()
+STRING(REGEX MATCHALL [[<Label>label2</Label>]] matches "${_test_contents}")
+list(LENGTH matches n_matches)
+if(NOT n_matches EQUAL 1)
+ string(APPEND RunCMake_TEST_FAILED "expected 1 match for label2, found ${n_matches}")
+endif()
+STRING(REGEX MATCHALL [[<Label>label3</Label>]] matches "${_test_contents}")
+list(LENGTH matches n_matches)
+if(NOT n_matches EQUAL 1)
+ string(APPEND RunCMake_TEST_FAILED "expected 1 match for label3, found ${n_matches}")
+endif()
+
+# Check test output.
+if(NOT _test_contents MATCHES "<Value>before\nafter\n</Value>")
+ string(APPEND RunCMake_TEST_FAILED "Could not find expected output in Test.xml")
+endif()
diff --git a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake
index 0095db0de..7e0928d5d 100644
--- a/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake
+++ b/Tests/RunCMake/ctest_test/TestMeasurements-check.cmake
@@ -10,13 +10,31 @@ endif()
if(NOT _test_contents MATCHES "<Value>1.4847</Value>")
string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value in Test.xml")
endif()
+# Check the other double measurement.
+if(NOT _test_contents MATCHES [[NamedMeasurement type="numeric/double" name="another_custom_value"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag(2) for type='numeric/double' in Test.xml")
+endif()
+if(NOT _test_contents MATCHES "<Value>1.8474</Value>")
+ string(APPEND RunCMake_TEST_FAILED "Could not find expected measurement value(2) in Test.xml")
+endif()
# Check img measurement.
if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage" type="image/png" encoding="base64"]])
string(APPEND RunCMake_TEST_FAILED
"Could not find expected <NamedMeasurement> tag for type='image/png' in Test.xml")
endif()
+# Check img measurement 2.
+if(NOT _test_contents MATCHES [[NamedMeasurement name="TestImage2" type="image/png" encoding="base64"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag(2) for type='image/png' in Test.xml")
+endif()
# Check file measurement.
if(NOT _test_contents MATCHES [[NamedMeasurement name="my_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]])
string(APPEND RunCMake_TEST_FAILED
"Could not find expected <NamedMeasurement> tag for type='file' in Test.xml")
endif()
+# Check file measurement 2.
+if(NOT _test_contents MATCHES [[NamedMeasurement name="another_test_input_data" encoding="base64" compression="tar/gzip" filename="cmake-logo-16.png" type="file"]])
+ string(APPEND RunCMake_TEST_FAILED
+ "Could not find expected <NamedMeasurement> tag(2) for type='file' in Test.xml")
+endif()
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
index 5b863220a..9ed17286f 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-notfile-all-stderr.txt
@@ -1,2 +1,4 @@
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
- file Could not resolve file libtest\.so$
+ file Could not resolve runtime dependencies:
+
+ libtest\.so$
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt
index eaca5121b..51010a19d 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/linux-unresolved-all-stderr.txt
@@ -1,2 +1,4 @@
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
- file Could not resolve file libunresolved\.so$
+ file Could not resolve runtime dependencies:
+
+ libunresolved\.so$
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt
index 01762b45f..5743d27f4 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/macos-unresolved-all-stderr.txt
@@ -1,2 +1,4 @@
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
- file Could not resolve file @rpath/libunresolved\.dylib$
+ file Could not resolve runtime dependencies:
+
+ @rpath/libunresolved\.dylib$
diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt
index a20654c5a..0efcb57d4 100644
--- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt
+++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/windows-unresolved-all-stderr.txt
@@ -1,2 +1,4 @@
^CMake Error at cmake_install\.cmake:[0-9]+ \(file\):
- file Could not resolve file (lib)?unresolved\.dll$
+ file Could not resolve runtime dependencies:
+
+ (lib)?unresolved\.dll$
diff --git a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
index eb7b49730..1ca2e757a 100644
--- a/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
@@ -1,8 +1,6 @@
include(RunCMake)
-if(HAVE_ELF_H)
- run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake)
-endif()
+run_cmake_command(ELF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/ELF.cmake)
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
run_cmake_command(XCOFF ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/XCOFF.cmake)
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 9efd3f493..aff4735f4 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -97,7 +97,9 @@ if(NOT WIN32
run_cmake(READ_SYMLINK)
run_cmake(READ_SYMLINK-noexist)
run_cmake(READ_SYMLINK-notsymlink)
- run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN)
+ if(NOT CYGWIN)
+ run_cmake(INSTALL-FOLLOW_SYMLINK_CHAIN)
+ endif()
endif()
run_cmake(REAL_PATH-unexpected-arg)
diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt
new file mode 100644
index 000000000..185720bbb
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt
@@ -0,0 +1,4 @@
+.*find_library considered the following locations.*
+.*\(lib\)library_no_exist\(\\.tbd\|\\.dylib\|\\.so\|\\.a\).*
+.*The item was found at.*
+.*lib/libcreated.a.*
diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt
new file mode 100644
index 000000000..501ec0ff5
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromScriptMode-stderr-windows.txt
@@ -0,0 +1,4 @@
+.*find_library considered the following locations.*
+.*\(\|lib\)library_no_exist\(\\.lib\|\\.dll\\.a\|\\.a\).*
+.*The item was found at.*
+.*lib/libcreated.a.*
diff --git a/Tests/RunCMake/find_library/FromScriptMode-stderr.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr.txt
new file mode 100644
index 000000000..046f68076
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromScriptMode-stderr.txt
@@ -0,0 +1,4 @@
+.*find_library considered the following locations.*
+.*\(lib\)library_no_exist\(\\.so\|\\.a\).*
+.*The item was found at.*
+.*lib/libcreated.a.*
diff --git a/Tests/RunCMake/find_library/FromScriptMode.cmake b/Tests/RunCMake/find_library/FromScriptMode.cmake
new file mode 100644
index 000000000..4d3c6990a
--- /dev/null
+++ b/Tests/RunCMake/find_library/FromScriptMode.cmake
@@ -0,0 +1,15 @@
+
+if(TEMP_DIR)
+ file(REMOVE_RECURSE "${TEMP_DIR}")
+ file(MAKE_DIRECTORY "${TEMP_DIR}")
+ file(MAKE_DIRECTORY "${TEMP_DIR}/lib")
+ file(WRITE "${TEMP_DIR}/lib/libcreated.a" "created")
+endif()
+
+set(CMAKE_FIND_DEBUG_MODE 1)
+find_library(CREATED_LIBRARY NAMES library_no_exist)
+
+set(CMAKE_PREFIX_PATH "${TEMP_DIR}")
+find_library(CREATED_LIBRARY NAMES created)
+message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+set(CMAKE_FIND_DEBUG_MODE 0)
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index e2971733b..ad02c821c 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -10,3 +10,5 @@ endif()
run_cmake(PrefixInPATH)
run_cmake(Required)
run_cmake(NO_CACHE)
+
+run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp")
diff --git a/Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt b/Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt
new file mode 100644
index 000000000..0db83aa8b
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0084-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0084-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0084 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt b/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormalForceRequired-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt b/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt
new file mode 100644
index 000000000..f6c0b44a0
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt
@@ -0,0 +1,20 @@
+CMake Error at MissingNormalForceRequired.cmake:2 \(find_package\):
+ No "FindNotHere.cmake" found in CMAKE_MODULE_PATH\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Warning \(dev\) at MissingNormalForceRequired.cmake:2 \(find_package\):
+ FindNotHere.cmake must either be part of this project itself, in this case
+ adjust CMAKE_MODULE_PATH so that it points to the correct location inside
+ its source tree\.
+
+ Or it must be installed by a package which has already been found via
+ find_package\(\)\. In this case make sure that package has indeed been found
+ and adjust CMAKE_MODULE_PATH to contain the location where that package has
+ installed FindNotHere\.cmake\. This must be a location provided by that
+ package. This error in general means that the buildsystem of this project
+ is relying on a Find-module without ensuring that it is actually available\.
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it\.
diff --git a/Tests/RunCMake/find_package/MissingNormalForceRequired.cmake b/Tests/RunCMake/find_package/MissingNormalForceRequired.cmake
new file mode 100644
index 000000000..5935316c8
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormalForceRequired.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_REQUIRE_FIND_PACKAGE_NotHere ON)
+find_package(NotHere MODULE)
+message(FATAL_ERROR "This error must not be reachable.")
diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt b/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt b/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt
new file mode 100644
index 000000000..b4fdd98d2
--- /dev/null
+++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash-stderr.txt
@@ -0,0 +1,11 @@
+CMake Error at RequiredOptionValuesClash.cmake:4 \(find_package\):
+ find_package for module Foo was made REQUIRED with
+ CMAKE_REQUIRE_FIND_PACKAGE_Foo but CMAKE_DISABLE_FIND_PACKAGE_Foo is
+ enabled. A REQUIRED package cannot be disabled.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
++
+CMake Error at RequiredOptionValuesClash.cmake:5 \(message\):
+ This error must not be reachable\.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake b/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake
new file mode 100644
index 000000000..04fece729
--- /dev/null
+++ b/Tests/RunCMake/find_package/RequiredOptionValuesClash.cmake
@@ -0,0 +1,5 @@
+set(CMAKE_DISABLE_FIND_PACKAGE_Foo ON)
+set(CMAKE_REQUIRE_FIND_PACKAGE_Foo ON)
+
+find_package(Foo)
+message(FATAL_ERROR "This error must not be reachable.")
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index 3ba04c8bd..b20a88950 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -6,6 +6,7 @@ run_cmake(ComponentRequiredAndOptional)
run_cmake(FromPATHEnv)
run_cmake(FromPrefixPath)
run_cmake(MissingNormal)
+run_cmake(MissingNormalForceRequired)
run_cmake(MissingNormalRequired)
run_cmake(MissingNormalVersion)
run_cmake(MissingNormalWarnNoModuleOld)
@@ -23,6 +24,7 @@ run_cmake(PackageRootNestedConfig)
run_cmake(PackageRootNestedModule)
run_cmake(PolicyPush)
run_cmake(PolicyPop)
+run_cmake(RequiredOptionValuesClash)
run_cmake(SetFoundFALSE)
run_cmake(WrongVersion)
run_cmake(WrongVersionConfig)
diff --git a/Tests/RunCMake/if/IncompleteMatches-stdout.txt b/Tests/RunCMake/if/IncompleteMatches-stdout.txt
new file mode 100644
index 000000000..634d98849
--- /dev/null
+++ b/Tests/RunCMake/if/IncompleteMatches-stdout.txt
@@ -0,0 +1,6 @@
+-- Test #1 passed
+-- Test #2 passed
+-- Test #3 passed
+-- Test #4 passed
+-- Test #5 passed
+-- Test #6 passed
diff --git a/Tests/RunCMake/if/IncompleteMatches.cmake b/Tests/RunCMake/if/IncompleteMatches.cmake
new file mode 100644
index 000000000..7142cfc32
--- /dev/null
+++ b/Tests/RunCMake/if/IncompleteMatches.cmake
@@ -0,0 +1,36 @@
+if(MATCHES)
+ message(SEND_ERROR "Test #1 failed")
+else()
+ message(STATUS "Test #1 passed")
+endif()
+
+if("" MATCHES "")
+ message(STATUS "Test #2 passed")
+else()
+ message(SEND_ERROR "Test #2 failed")
+endif()
+
+if(MATCHES RHS)
+ message(SEND_ERROR "Test #3 failed")
+else()
+ message(STATUS "Test #3 passed")
+endif()
+
+set(RHS "")
+if(MATCHES RHS)
+ message(SEND_ERROR "Test #4 failed")
+else()
+ message(STATUS "Test #4 passed")
+endif()
+
+if(MATCHES "^$")
+ message(SEND_ERROR "Test #5 failed")
+else()
+ message(STATUS "Test #5 passed")
+endif()
+
+if("" MATCHES "^$")
+ message(STATUS "Test #6 passed")
+else()
+ message(SEND_ERROR "Test #6 failed")
+endif()
diff --git a/Tests/RunCMake/if/IncompleteMatchesFail-result.txt b/Tests/RunCMake/if/IncompleteMatchesFail-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/if/IncompleteMatchesFail-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt b/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt
new file mode 100644
index 000000000..6e8ac80be
--- /dev/null
+++ b/Tests/RunCMake/if/IncompleteMatchesFail-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at IncompleteMatchesFail\.cmake:1 \(if\):
+ if given arguments:
+
+ "LHS" "MATCHES"
+
+ Unknown arguments specified
diff --git a/Tests/RunCMake/if/IncompleteMatchesFail.cmake b/Tests/RunCMake/if/IncompleteMatchesFail.cmake
new file mode 100644
index 000000000..a3ef2b8ae
--- /dev/null
+++ b/Tests/RunCMake/if/IncompleteMatchesFail.cmake
@@ -0,0 +1,2 @@
+if(LHS MATCHES)
+endif()
diff --git a/Tests/RunCMake/if/RunCMakeTest.cmake b/Tests/RunCMake/if/RunCMakeTest.cmake
index f54edf7ed..6baa84059 100644
--- a/Tests/RunCMake/if/RunCMakeTest.cmake
+++ b/Tests/RunCMake/if/RunCMakeTest.cmake
@@ -9,7 +9,11 @@ run_cmake(duplicate-else-after-elseif)
run_cmake(elseif-message)
run_cmake(misplaced-elseif)
+run_cmake(unbalanced-parenthesis)
+
run_cmake(MatchesSelf)
+run_cmake(IncompleteMatches)
+run_cmake(IncompleteMatchesFail)
run_cmake(TestNameThatExists)
run_cmake(TestNameThatDoesNotExist)
diff --git a/Tests/RunCMake/if/unbalanced-parenthesis-result.txt b/Tests/RunCMake/if/unbalanced-parenthesis-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/if/unbalanced-parenthesis-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt b/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt
new file mode 100644
index 000000000..770ccb8f1
--- /dev/null
+++ b/Tests/RunCMake/if/unbalanced-parenthesis-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at unbalanced-parenthesis\.cmake:[0-9]+ \(if\):
+ if given arguments:
+
+ "NOT" "\(" "IN_LIST" "some_list"
+
+ mismatched parenthesis in condition
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/if/unbalanced-parenthesis.cmake b/Tests/RunCMake/if/unbalanced-parenthesis.cmake
new file mode 100644
index 000000000..c51c7557f
--- /dev/null
+++ b/Tests/RunCMake/if/unbalanced-parenthesis.cmake
@@ -0,0 +1,8 @@
+set(var_with_paren "(")
+set(some_list "")
+
+if(NOT ${var_with_paren} IN_LIST some_list)
+ message(STATUS "Never prints")
+else()
+ message(STATUS "Never prints")
+endif()
diff --git a/Tests/RunCMake/install/CMP0087-OLD-stderr.txt b/Tests/RunCMake/install/CMP0087-OLD-stderr.txt
new file mode 100644
index 000000000..5233ebc5b
--- /dev/null
+++ b/Tests/RunCMake/install/CMP0087-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning at CMP0087-OLD/CMakeLists.txt:5 \(cmake_policy\):
+ The OLD behavior for policy CMP0087 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.$
diff --git a/Tests/RunCMake/string/Timestamp-stderr.txt b/Tests/RunCMake/string/Timestamp-stderr.txt
index cd4dcb37e..d54777bd7 100644
--- a/Tests/RunCMake/string/Timestamp-stderr.txt
+++ b/Tests/RunCMake/string/Timestamp-stderr.txt
@@ -1 +1 @@
-RESULT=2005-08-07 23:19:49 Sunday=Sun August=Aug 05 day=219 wd=0 week=32 %I=11 epoch=1123456789
+RESULT=2005-08-07 23:19:49 Sunday=Sun August=Aug 05 day=219 wd=0 week=32 w_iso=31 %I=11 epoch=1123456789
diff --git a/Tests/RunCMake/string/Timestamp.cmake b/Tests/RunCMake/string/Timestamp.cmake
index cba258d12..7fd6d72b0 100644
--- a/Tests/RunCMake/string/Timestamp.cmake
+++ b/Tests/RunCMake/string/Timestamp.cmake
@@ -1,3 +1,3 @@
set(ENV{SOURCE_DATE_EPOCH} "1123456789")
-string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %A=%a %B=%b %y day=%j wd=%w week=%U %%I=%I epoch=%s" UTC)
+string(TIMESTAMP RESULT "%Y-%m-%d %H:%M:%S %A=%a %B=%b %y day=%j wd=%w week=%U w_iso=%V %%I=%I epoch=%s" UTC)
message("RESULT=${RESULT}")
diff --git a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
index 5b4761c60..cf4c540c7 100644
--- a/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/cxx_not_enabled-stderr.txt
@@ -1,4 +1,2 @@
-^CMake Error at cxx_not_enabled.cmake:[0-9]+ \(target_compile_features\):
- target_compile_features cannot use features from non-enabled language CXX
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
+^CMake Error:.*CMake can not determine linker language for target: main.*
+CMake Generate step failed. Build files cannot be regenerated correctly.$
diff --git a/Tests/RunCMake/while/RunCMakeTest.cmake b/Tests/RunCMake/while/RunCMakeTest.cmake
index 7da80ace3..bb9b99101 100644
--- a/Tests/RunCMake/while/RunCMakeTest.cmake
+++ b/Tests/RunCMake/while/RunCMakeTest.cmake
@@ -5,3 +5,5 @@ run_cmake(EndMissing)
run_cmake(EndMismatch)
run_cmake(EndAlone)
run_cmake(EndAloneArgs)
+
+run_cmake(unbalanced-parenthesis)
diff --git a/Tests/RunCMake/while/unbalanced-parenthesis-result.txt b/Tests/RunCMake/while/unbalanced-parenthesis-result.txt
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/Tests/RunCMake/while/unbalanced-parenthesis-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt
new file mode 100644
index 000000000..9d4132c5a
--- /dev/null
+++ b/Tests/RunCMake/while/unbalanced-parenthesis-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at unbalanced-parenthesis.cmake:[0-9]+ \(while\):
+ had incorrect arguments:
+
+ "NOT" "\(" "IN_LIST" "some_list"
+
+ mismatched parenthesis in condition
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/while/unbalanced-parenthesis.cmake b/Tests/RunCMake/while/unbalanced-parenthesis.cmake
new file mode 100644
index 000000000..7a12701e6
--- /dev/null
+++ b/Tests/RunCMake/while/unbalanced-parenthesis.cmake
@@ -0,0 +1,8 @@
+set(var_with_paren "(")
+set(some_list "")
+
+while(NOT ${var_with_paren} IN_LIST some_list)
+ message(STATUS "Never prints")
+endwhile()
+
+message(STATUS "Never prints")
diff --git a/Tests/UseSWIG/CMakeLists.txt b/Tests/UseSWIG/CMakeLists.txt
index 6c0d5e483..c3f9e033a 100644
--- a/Tests/UseSWIG/CMakeLists.txt
+++ b/Tests/UseSWIG/CMakeLists.txt
@@ -67,7 +67,7 @@ add_test(NAME UseSWIG.BasicPerl COMMAND
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2"
- AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode")
+ AND CMAKE_GENERATOR MATCHES "Make|Ninja|Xcode|Visual Studio (1[1-9]|[2-9][0-9])")
add_test(NAME UseSWIG.Depfile.BasicPython COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
@@ -76,7 +76,6 @@ if(SWIG_FOUND AND NOT SWIG_VERSION VERSION_LESS "4.0.2"
${build_generator_args}
--build-project TestBasicPython
--build-options ${build_options} -DSWIG_USE_SWIG_DEPENDENCIES=ON
- "-DSWIG_OUTFILE_DIR=${CMake_BINARY_DIR}/Tests/UseSWIG/BasicPython.Depfile"
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
add_test(NAME UseSWIG.Depfile.BasicPerl COMMAND
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index 0ccb72124..69b4e2fd4 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeDeveloperReference_STANDALONE 1)
- cmake_minimum_required(VERSION 3.1...3.19 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.20 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index f1bdcc4ca..8c55c85f8 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -101,6 +101,7 @@
# Wrappers for 3rd-party libraries
{ include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] },
+ { include: [ "@<.*json/config.h>", private, "<cm3p/json/value.h>", public ] },
{ include: [ "@<.*json/forwards.h>", private, "<cm3p/json/value.h>", public ] },
{ include: [ "@<.*uv/.+\\.h>", private, "<cm3p/uv.h>", public ] },
{ include: [ "@<.*expat_external.h>", private, "<cm3p/expat.h>", public ] },
diff --git a/Utilities/KWIML/include/kwiml/int.h b/Utilities/KWIML/include/kwiml/int.h
index b2e14d5f2..25a063aaf 100644
--- a/Utilities/KWIML/include/kwiml/int.h
+++ b/Utilities/KWIML/include/kwiml/int.h
@@ -162,7 +162,11 @@ An includer may test the following macros after inclusion:
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
# define KWIML_INT_HAVE_INTTYPES_H 1
#elif defined(_MSC_VER) /* MSVC */
-# define KWIML_INT_NO_INTTYPES_H 1
+# if _MSC_VER >= 1800
+# define KWIML_INT_HAVE_INTTYPES_H 1
+# else
+# define KWIML_INT_NO_INTTYPES_H 1
+# endif
#elif defined(__BORLANDC__) /* Borland */
# define KWIML_INT_NO_INTTYPES_H 1
#elif defined(__WATCOMC__) /* Watcom */
@@ -272,6 +276,15 @@ An includer may test the following macros after inclusion:
# define KWIML_INT_BROKEN_PRIXPTR 1
#endif
+#if defined(_MSC_VER) && _MSC_VER < 1900
+ /* MSVC scanf seems broken on 8-bit sizes until 19.00 */
+# define KWIML_INT_BROKEN_SCNd8 1
+# define KWIML_INT_BROKEN_SCNi8 1
+# define KWIML_INT_BROKEN_SCNo8 1
+# define KWIML_INT_BROKEN_SCNu8 1
+# define KWIML_INT_BROKEN_SCNx8 1
+#endif
+
#if (defined(__SUNPRO_C)||defined(__SUNPRO_CC)) && defined(_CHAR_IS_UNSIGNED)
# define KWIML_INT_BROKEN_INT8_T 1 /* system type defined incorrectly */
#elif defined(__BORLANDC__) && defined(_CHAR_UNSIGNED)
@@ -303,7 +316,7 @@ An includer may test the following macros after inclusion:
#elif defined(__BORLANDC__)
# define KWIML_INT_private_NO_SCN8
# define KWIML_INT_private_NO_SCN64
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && _MSC_VER < 1900
# define KWIML_INT_private_NO_SCN8
#elif defined(__WATCOMC__)
# define KWIML_INT_private_NO_SCN8
diff --git a/Utilities/Release/win/x86/Dockerfile b/Utilities/Release/win/x86/Dockerfile
index d5a036a79..a4f744578 100644
--- a/Utilities/Release/win/x86/Dockerfile
+++ b/Utilities/Release/win/x86/Dockerfile
@@ -11,10 +11,8 @@ ARG FROM_IMAGE_NAME=kitware/cmake:build-win-x86-deps-2020-04-27
ARG FROM_IMAGE_DIGEST=@sha256:04e229c0c0ba2247855d0e8c0fb87c1686f983adbafa4ce413e61b3905edb76b
ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST
-FROM $FROM_IMAGE as source
+FROM $FROM_IMAGE as build
COPY . C:\cmake\src\cmake
-
-FROM source as build
ARG ARCH="x86_64"
ARG TEST="true"
RUN \cmake\src\cmake\Utilities\Release\win\x86\build.bat %ARCH% %TEST%
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 34ff4de57..dd8e7a8e0 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_77_0"
+readonly tag="curl-7_79_1"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-elf.bash b/Utilities/Scripts/update-elf.bash
new file mode 100755
index 000000000..1a065bad8
--- /dev/null
+++ b/Utilities/Scripts/update-elf.bash
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+set -e
+set -x
+shopt -s dotglob
+
+readonly name="elf"
+readonly ownership="FreeBSD Upstream <kwrobot@kitware.com>"
+readonly subtree="Utilities/cmelf"
+readonly repo="https://github.com/freebsd/freebsd-src.git"
+readonly tag="main"
+readonly shortlog=false
+readonly paths="
+ sys/sys/elf32.h
+ sys/sys/elf64.h
+ sys/sys/elf_common.h
+"
+
+extract_source () {
+ git_archive
+ pushd "${extractdir}/${name}-reduced"
+ echo "* -whitespace" > .gitattributes
+ mv sys/sys/* .
+ sed -i -e 's/<sys\/elf_common.h>/"elf_common.h"/g' -e 's/u_int32_t/uint32_t/g' *.h
+ popd
+}
+
+. "${BASH_SOURCE%/*}/update-third-party.bash"
diff --git a/Utilities/Scripts/update-jsoncpp.bash b/Utilities/Scripts/update-jsoncpp.bash
index f8fe54462..5ed00e7cf 100755
--- a/Utilities/Scripts/update-jsoncpp.bash
+++ b/Utilities/Scripts/update-jsoncpp.bash
@@ -8,7 +8,7 @@ readonly name="jsoncpp"
readonly ownership="JsonCpp Upstream <kwrobot@kitware.com>"
readonly subtree="Utilities/cmjsoncpp"
readonly repo="https://github.com/open-source-parsers/jsoncpp.git"
-readonly tag="1.8.2"
+readonly tag="1.9.4"
readonly shortlog=false
readonly paths="
LICENSE
diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash
index 3db89ff73..3a24e2b3e 100755
--- a/Utilities/Scripts/update-libarchive.bash
+++ b/Utilities/Scripts/update-libarchive.bash
@@ -8,7 +8,7 @@ readonly name="LibArchive"
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
readonly subtree="Utilities/cmlibarchive"
readonly repo="https://github.com/libarchive/libarchive.git"
-readonly tag="v3.4.2"
+readonly tag="v3.5.1"
readonly shortlog=false
readonly paths="
CMakeLists.txt
diff --git a/Utilities/Scripts/update-third-party.bash b/Utilities/Scripts/update-third-party.bash
index 0d0a667c1..bfe6828de 100644
--- a/Utilities/Scripts/update-third-party.bash
+++ b/Utilities/Scripts/update-third-party.bash
@@ -42,6 +42,22 @@
# For convenience, the function may use the "git_archive" function which
# does a standard "git archive" extraction using the (optional) "paths"
# variable to only extract a subset of the source tree.
+#
+# Dependencies
+#
+# To update third party packages from git repositories with submodule,
+# you will need to install the "git-archive-all" Python package with
+#
+# pip install git-archive-all
+#
+# or install it from https://github.com/Kentzo/git-archive-all.
+#
+# This package installs a script named "git-archive-all" where pip
+# installs executables. If you run pip under your user privileges (i.e.,
+# not using "sudo"), this location may be $HOME/.local/bin. Make sure
+# that directory is in your path so that git can find the
+# "git-archive-all" script.
+#
########################################################################
########################################################################
@@ -52,11 +68,24 @@ git_archive () {
tar -C "$extractdir" -x
}
+confirm_archive_all_exists () {
+ which git-archive-all || die "git requires an archive-all command. Please run 'pip install git-archive-all'"
+}
+
+git_archive_all () {
+ confirm_archive_all_exists
+ local tmptarball="temp.tar"
+ git archive-all --prefix="" "$tmptarball"
+ mkdir -p "$extractdir/$name-reduced"
+ tar -C "$extractdir/$name-reduced" -xf "$tmptarball" $paths
+ rm -f "$tmptarball"
+}
+
disable_custom_gitattributes() {
pushd "${extractdir}/${name}-reduced"
# Git does not allow custom attributes in a subdirectory where we
# are about to merge the `.gitattributes` file, so disable them.
- sed -i '/^\[attr\]/ {s/^/#/}' .gitattributes
+ sed -i '/^\[attr\]/ {s/^/#/;}' .gitattributes
popd
}
@@ -71,6 +100,9 @@ warn () {
readonly regex_date='20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
readonly basehash_regex="$name $regex_date ([0-9a-f]*)"
+readonly toplevel_dir="$( git rev-parse --show-toplevel )"
+
+cd "$toplevel_dir"
########################################################################
# Sanity checking
@@ -95,7 +127,7 @@ if [ ! -d "$(git rev-parse --show-toplevel)/$subtree" ]; then
else
readonly basehash="$( git rev-list --author="$ownership" --grep="$basehash_regex" -n 1 HEAD )"
fi
-readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p}' | egrep '^[0-9a-f]+$' )"
+readonly upstream_old_short="$( git cat-file commit "$basehash" | sed -n '/'"$basehash_regex"'/ {s/.*(//;s/)//;p;}' | egrep '^[0-9a-f]+$' )"
[ -n "$basehash" ] || \
warn "'basehash' is empty; performing initial import"
@@ -111,7 +143,7 @@ readonly extractdir="$workdir/extract"
trap "rm -rf '$workdir'" EXIT
# Get upstream
-git clone "$repo" "$upstreamdir"
+git clone --recursive "$repo" "$upstreamdir"
if [ -n "$basehash" ]; then
# Remove old worktrees
@@ -120,7 +152,7 @@ if [ -n "$basehash" ]; then
git worktree add "$extractdir" "$basehash"
# Clear out the working tree
pushd "$extractdir"
- git ls-files | xargs rm -v
+ git ls-files -z --recurse-submodules | xargs -0 rm -v
find . -type d -empty -delete
popd
else
@@ -132,6 +164,8 @@ fi
# Extract the subset of upstream we care about
pushd "$upstreamdir"
git checkout "$tag"
+git submodule sync --recursive
+git submodule update --recursive --init
readonly upstream_hash="$( git rev-parse HEAD )"
readonly upstream_hash_short="$( git rev-parse --short=8 "$upstream_hash" )"
readonly upstream_datetime="$( git rev-list "$upstream_hash" --format='%ci' -n 1 | grep -e "^$regex_date" )"
diff --git a/Utilities/Scripts/update-zstd.bash b/Utilities/Scripts/update-zstd.bash
index a9b62f949..48ca5a17d 100755
--- a/Utilities/Scripts/update-zstd.bash
+++ b/Utilities/Scripts/update-zstd.bash
@@ -8,7 +8,7 @@ readonly name="zstd"
readonly ownership="zstd upstream <kwrobot@kitware.com>"
readonly subtree="Utilities/cmzstd"
readonly repo="https://github.com/facebook/zstd.git"
-readonly tag="v1.4.5"
+readonly tag="v1.5.0"
readonly shortlog=false
readonly paths="
LICENSE
@@ -23,7 +23,7 @@ readonly paths="
lib/deprecated/*.h
lib/dictBuilder/*.c
lib/dictBuilder/*.h
- lib/zstd.h
+ lib/*.h
"
extract_source () {
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index 32efd4842..c8a970dca 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeHelp_STANDALONE 1)
- cmake_minimum_required(VERSION 3.1...3.19 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.1...3.20 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
@@ -58,6 +58,13 @@ configure_file(conf.py.in conf.py @ONLY)
set(doc_formats "")
if(SPHINX_HTML)
list(APPEND doc_formats html)
+
+ # we provide the path to the produced html output in the console
+ # for tools that support URI protocol schemes
+ set(html_extra_commands
+ COMMAND ${CMAKE_COMMAND} -E echo "sphinx-build html: HTML documentation generated in file://${CMAKE_CURRENT_BINARY_DIR}/html/index.html"
+ )
+
endif()
if(SPHINX_MAN)
list(APPEND doc_formats man)
diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake
index bab30463f..7e38df945 100644
--- a/Utilities/cmThirdPartyChecks.cmake
+++ b/Utilities/cmThirdPartyChecks.cmake
@@ -180,6 +180,7 @@ if(WIN32)
set(HAVE_STRERROR_R 0)
set(HAVE_STRNCMPI 0)
set(HAVE_STRNCPY_S 1)
+ set(HAVE_STRNLEN 1)
set(HAVE_STROPTS_H 0)
set(HAVE__STRTOI64 1)
set(HAVE_STRTOLL 1)
diff --git a/Utilities/cmcurl/CMake/CurlTests.c b/Utilities/cmcurl/CMake/CurlTests.c
index 2fcce1bb3..e418146b4 100644
--- a/Utilities/cmcurl/CMake/CurlTests.c
+++ b/Utilities/cmcurl/CMake/CurlTests.c
@@ -71,21 +71,15 @@ main ()
}
#endif
-/* tests for gethostbyaddr_r or gethostbyname_r */
-#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \
- defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
- defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
- defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \
+/* tests for gethostbyname_r */
+#if defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
# define _REENTRANT
/* no idea whether _REENTRANT is always set, just invent a new flag */
# define TEST_GETHOSTBYFOO_REENTRANT
#endif
-#if defined(HAVE_GETHOSTBYADDR_R_5) || \
- defined(HAVE_GETHOSTBYADDR_R_7) || \
- defined(HAVE_GETHOSTBYADDR_R_8) || \
- defined(HAVE_GETHOSTBYNAME_R_3) || \
+#if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(TEST_GETHOSTBYFOO_REENTRANT)
@@ -98,18 +92,10 @@ int main(void)
int type = 0;
struct hostent h;
int rc = 0;
-#if defined(HAVE_GETHOSTBYADDR_R_5) || \
- defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \
- \
- defined(HAVE_GETHOSTBYNAME_R_3) || \
+#if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
struct hostent_data hdata;
-#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
- defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
- defined(HAVE_GETHOSTBYADDR_R_8) || \
- defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
- \
- defined(HAVE_GETHOSTBYNAME_R_5) || \
+#elif defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
@@ -118,24 +104,6 @@ int main(void)
struct hostent *hp;
#endif
-#ifndef gethostbyaddr_r
- (void)gethostbyaddr_r;
-#endif
-
-#if defined(HAVE_GETHOSTBYADDR_R_5) || \
- defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT)
- rc = gethostbyaddr_r(address, length, type, &h, &hdata);
- (void)rc;
-#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
- defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT)
- hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop);
- (void)hp;
-#elif defined(HAVE_GETHOSTBYADDR_R_8) || \
- defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT)
- rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop);
- (void)rc;
-#endif
-
#if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
rc = gethostbyname_r(address, &h, &hdata);
@@ -214,37 +182,6 @@ if (sizeof (bool *) )
#include <float.h>
int main() { return 0; }
#endif
-#ifdef HAVE_INET_NTOA_R_DECL
-#include <arpa/inet.h>
-
-typedef void (*func_type)();
-
-int main()
-{
-#ifndef inet_ntoa_r
- func_type func;
- func = (func_type)inet_ntoa_r;
- (void)func;
-#endif
- return 0;
-}
-#endif
-#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT
-#define _REENTRANT
-#include <arpa/inet.h>
-
-typedef void (*func_type)();
-
-int main()
-{
-#ifndef inet_ntoa_r
- func_type func;
- func = (func_type)&inet_ntoa_r;
- (void)func;
-#endif
- return 0;
-}
-#endif
#ifdef HAVE_GETADDRINFO
#include <netdb.h>
#include <sys/types.h>
@@ -361,7 +298,7 @@ main ()
/* IoctlSocket source code */
long flags = 0;
- if(0 != ioctlsocket(0, FIONBIO, &flags))
+ if(0 != IoctlSocket(0, FIONBIO, &flags))
return 1;
;
return 0;
diff --git a/Utilities/cmcurl/CMake/OtherTests.cmake b/Utilities/cmcurl/CMake/OtherTests.cmake
index bbd463250..7fda7aca3 100644
--- a/Utilities/cmcurl/CMake/OtherTests.cmake
+++ b/Utilities/cmcurl/CMake/OtherTests.cmake
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -54,6 +54,40 @@ if(1) # CMake hard-codes these
set(RECV_TYPE_ARG4 "int")
set(RECV_TYPE_RETV "ssize_t")
else()
+function(curl_cv_func_recv_run_test recv_retv recv_arg1 recv_arg2 recv_arg3 recv_arg4)
+ unset(curl_cv_func_recv_test CACHE)
+ check_c_source_compiles("
+ ${_source_epilogue}
+ #ifdef WINSOCK_API_LINKAGE
+ WINSOCK_API_LINKAGE
+ #endif
+ extern ${recv_retv} ${signature_call_conv}
+ recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
+ int main(void) {
+ ${recv_arg1} s=0;
+ ${recv_arg2} buf=0;
+ ${recv_arg3} len=0;
+ ${recv_arg4} flags=0;
+ ${recv_retv} res = recv(s, buf, len, flags);
+ (void) res;
+ return 0;
+ }"
+ curl_cv_func_recv_test)
+ message(STATUS
+ "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
+ if(curl_cv_func_recv_test)
+ set(curl_cv_func_recv_args
+ "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}" PARENT_SCOPE)
+ set(RECV_TYPE_ARG1 "${recv_arg1}" PARENT_SCOPE)
+ set(RECV_TYPE_ARG2 "${recv_arg2}" PARENT_SCOPE)
+ set(RECV_TYPE_ARG3 "${recv_arg3}" PARENT_SCOPE)
+ set(RECV_TYPE_ARG4 "${recv_arg4}" PARENT_SCOPE)
+ set(RECV_TYPE_RETV "${recv_retv}" PARENT_SCOPE)
+ set(HAVE_RECV 1 PARENT_SCOPE)
+ set(curl_cv_func_recv_done 1 PARENT_SCOPE)
+ endif()
+endfunction()
+
check_c_source_compiles("${_source_epilogue}
int main(void) {
recv(0, 0, 0, 0);
@@ -61,43 +95,16 @@ int main(void) {
}" curl_cv_recv)
if(curl_cv_recv)
if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL "unknown")
+ if(APPLE)
+ curl_cv_func_recv_run_test("ssize_t" "int" "void *" "size_t" "int")
+ endif()
foreach(recv_retv "int" "ssize_t" )
foreach(recv_arg1 "SOCKET" "int" )
foreach(recv_arg2 "char *" "void *" )
foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int")
foreach(recv_arg4 "int" "unsigned int")
if(NOT curl_cv_func_recv_done)
- unset(curl_cv_func_recv_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${recv_retv} ${signature_call_conv}
- recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
- int main(void) {
- ${recv_arg1} s=0;
- ${recv_arg2} buf=0;
- ${recv_arg3} len=0;
- ${recv_arg4} flags=0;
- ${recv_retv} res = recv(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_recv_test)
- message(STATUS
- "Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
- if(curl_cv_func_recv_test)
- set(curl_cv_func_recv_args
- "${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}")
- set(RECV_TYPE_ARG1 "${recv_arg1}")
- set(RECV_TYPE_ARG2 "${recv_arg2}")
- set(RECV_TYPE_ARG3 "${recv_arg3}")
- set(RECV_TYPE_ARG4 "${recv_arg4}")
- set(RECV_TYPE_RETV "${recv_retv}")
- set(HAVE_RECV 1)
- set(curl_cv_func_recv_done 1)
- endif()
+ curl_cv_func_recv_run_test(${recv_retv} ${recv_arg1} ${recv_arg2} ${recv_arg3} ${recv_arg4})
endif()
endforeach()
endforeach()
@@ -130,6 +137,42 @@ if(1) # CMake hard-codes these
set(SEND_TYPE_ARG4 "int")
set(SEND_TYPE_RETV "ssize_t")
else()
+function(curl_cv_func_send_run_test send_retv send_arg1 send_arg2 send_arg3 send_arg4)
+ unset(curl_cv_func_send_test CACHE)
+ check_c_source_compiles("
+ ${_source_epilogue}
+ #ifdef WINSOCK_API_LINKAGE
+ WINSOCK_API_LINKAGE
+ #endif
+ extern ${send_retv} ${signature_call_conv}
+ send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
+ int main(void) {
+ ${send_arg1} s=0;
+ ${send_arg2} buf=0;
+ ${send_arg3} len=0;
+ ${send_arg4} flags=0;
+ ${send_retv} res = send(s, buf, len, flags);
+ (void) res;
+ return 0;
+ }"
+ curl_cv_func_send_test)
+ message(STATUS
+ "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
+ if(curl_cv_func_send_test)
+ string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
+ string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
+ set(curl_cv_func_send_args
+ "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}" PARENT_SCOPE)
+ set(SEND_TYPE_ARG1 "${send_arg1}" PARENT_SCOPE)
+ set(SEND_TYPE_ARG2 "${send_arg2}" PARENT_SCOPE)
+ set(SEND_TYPE_ARG3 "${send_arg3}" PARENT_SCOPE)
+ set(SEND_TYPE_ARG4 "${send_arg4}" PARENT_SCOPE)
+ set(SEND_TYPE_RETV "${send_retv}" PARENT_SCOPE)
+ set(HAVE_SEND 1 PARENT_SCOPE)
+ set(curl_cv_func_send_done 1 PARENT_SCOPE)
+ endif()
+endfunction()
+
check_c_source_compiles("${_source_epilogue}
int main(void) {
send(0, 0, 0, 0);
@@ -137,45 +180,16 @@ int main(void) {
}" curl_cv_send)
if(curl_cv_send)
if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
+ if(APPLE)
+ curl_cv_func_send_run_test("ssize_t" "int" "const void *" "size_t" "int")
+ endif()
foreach(send_retv "int" "ssize_t" )
foreach(send_arg1 "SOCKET" "int" "ssize_t" )
foreach(send_arg2 "const char *" "const void *" "void *" "char *")
foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int")
foreach(send_arg4 "int" "unsigned int")
if(NOT curl_cv_func_send_done)
- unset(curl_cv_func_send_test CACHE)
- check_c_source_compiles("
- ${_source_epilogue}
- #ifdef WINSOCK_API_LINKAGE
- WINSOCK_API_LINKAGE
- #endif
- extern ${send_retv} ${signature_call_conv}
- send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
- int main(void) {
- ${send_arg1} s=0;
- ${send_arg2} buf=0;
- ${send_arg3} len=0;
- ${send_arg4} flags=0;
- ${send_retv} res = send(s, buf, len, flags);
- (void) res;
- return 0;
- }"
- curl_cv_func_send_test)
- message(STATUS
- "Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
- if(curl_cv_func_send_test)
- string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
- string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
- set(curl_cv_func_send_args
- "${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}")
- set(SEND_TYPE_ARG1 "${send_arg1}")
- set(SEND_TYPE_ARG2 "${send_arg2}")
- set(SEND_TYPE_ARG3 "${send_arg3}")
- set(SEND_TYPE_ARG4 "${send_arg4}")
- set(SEND_TYPE_RETV "${send_retv}")
- set(HAVE_SEND 1)
- set(curl_cv_func_send_done 1)
- endif()
+ curl_cv_func_send_run_test("${send_retv}" "${send_arg1}" "${send_arg2}" "${send_arg3}" "${send_arg4}")
endif()
endforeach()
endforeach()
@@ -223,28 +237,6 @@ int main(void) {
return 0;
}" HAVE_STRUCT_TIMEVAL)
-set(HAVE_SIG_ATOMIC_T 1)
-set(CMAKE_REQUIRED_FLAGS)
-if(HAVE_SIGNAL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
- set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
-endif()
-check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
-if(HAVE_SIZEOF_SIG_ATOMIC_T)
- check_c_source_compiles("
- #ifdef HAVE_SIGNAL_H
- # include <signal.h>
- #endif
- int main(void) {
- static volatile sig_atomic_t dummy = 0;
- (void)dummy;
- return 0;
- }" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
- if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
- set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
- endif()
-endif()
-
if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
else()
@@ -262,6 +254,9 @@ endif()
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+ if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ # only try this on non-macOS
+
# if not cross-compilation...
include(CheckCSourceRuns)
set(CMAKE_REQUIRED_FLAGS "")
@@ -304,5 +299,6 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
}
return 0;
}" HAVE_POLL_FINE)
+ endif()
endif()
diff --git a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
index c39355711..dd653daea 100644
--- a/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
+++ b/Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
@@ -46,7 +46,6 @@ if(NOT UNIX)
set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1)
- set(HAVE_SGTTY_H 0)
set(HAVE_SIGNAL_H 1)
set(HAVE_SOCKIO_H 0)
set(HAVE_STDINT_H 0)
@@ -81,12 +80,8 @@ if(NOT UNIX)
set(HAVE_STRCASECMP 0)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
- set(HAVE_GETHOSTBYADDR 1)
set(HAVE_GETTIMEOFDAY 0)
set(HAVE_INET_ADDR 1)
- set(HAVE_INET_NTOA 1)
- set(HAVE_INET_NTOA_R 0)
- set(HAVE_PERROR 1)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SETVBUF 0)
set(HAVE_SIGSETJMP 0)
@@ -100,17 +95,10 @@ if(NOT UNIX)
set(HAVE_RAND_STATUS 0)
set(HAVE_GMTIME_R 0)
set(HAVE_LOCALTIME_R 0)
- set(HAVE_GETHOSTBYADDR_R 0)
set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL_FUNC 1)
set(HAVE_SIGNAL_MACRO 0)
- set(HAVE_GETHOSTBYADDR_R_5 0)
- set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0)
- set(HAVE_GETHOSTBYADDR_R_7 0)
- set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0)
- set(HAVE_GETHOSTBYADDR_R_8 0)
- set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_5 0)
@@ -121,8 +109,6 @@ if(NOT UNIX)
set(TIME_WITH_SYS_TIME 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
- set(HAVE_INET_NTOA_R_DECL 0)
- set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
if(ENABLE_IPV6)
set(HAVE_GETADDRINFO 1)
else()
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 16ef037cc..9eef01aaf 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -12,20 +12,32 @@ set(CURL_DISABLE_ALTSVC ON)
set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth")
set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
+set(CURL_DISABLE_DOH OFF)
set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?")
set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
+set(CURL_DISABLE_GETOPTIONS OFF)
set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
set(CURL_DISABLE_HSTS ON)
+set(CURL_DISABLE_HTTP_AUTH OFF)
set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
+set(CURL_DISABLE_LIBCURL_OPTION OFF)
+set(CURL_DISABLE_MIME OFF)
set(CURL_DISABLE_MQTT ON)
+set(CURL_DISABLE_NETRC OFF)
+set(CURL_DISABLE_NTLM OFF)
set(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG OFF)
+set(CURL_DISABLE_PARSEDATE OFF)
set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?")
+set(CURL_DISABLE_PROGRESS_METER OFF)
set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy")
set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?")
+set(CURL_DISABLE_SHUFFLE_DNS OFF)
+set(CURL_DISABLE_SMB OFF)
set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
+set(CURL_DISABLE_SOCKETPAIR OFF)
set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
@@ -272,43 +284,77 @@ if(0) # This code not needed for building within CMake.
include(CurlSymbolHiding)
endif()
-option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
-mark_as_advanced(HTTP_ONLY)
-option(CURL_DISABLE_FTP "disables FTP" OFF)
-mark_as_advanced(CURL_DISABLE_FTP)
-option(CURL_DISABLE_LDAP "disables LDAP" OFF)
-mark_as_advanced(CURL_DISABLE_LDAP)
-option(CURL_DISABLE_TELNET "disables Telnet" OFF)
-mark_as_advanced(CURL_DISABLE_TELNET)
+option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON)
+mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
+
+option(CURL_DISABLE_ALTSVC "disables alt-svc support" OFF)
+mark_as_advanced(CURL_DISABLE_ALTSVC)
+option(CURL_DISABLE_COOKIES "disables cookies support" OFF)
+mark_as_advanced(CURL_DISABLE_COOKIES)
+option(CURL_DISABLE_CRYPTO_AUTH "disables cryptographic authentication" OFF)
+mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
option(CURL_DISABLE_DICT "disables DICT" OFF)
mark_as_advanced(CURL_DISABLE_DICT)
+option(CURL_DISABLE_DOH "disables DNS-over-HTTPS" OFF)
+mark_as_advanced(CURL_DISABLE_DOH)
option(CURL_DISABLE_FILE "disables FILE" OFF)
mark_as_advanced(CURL_DISABLE_FILE)
-option(CURL_DISABLE_TFTP "disables TFTP" OFF)
-mark_as_advanced(CURL_DISABLE_TFTP)
+option(CURL_DISABLE_FTP "disables FTP" OFF)
+mark_as_advanced(CURL_DISABLE_FTP)
+option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing options to curl_easy_setopt" OFF)
+mark_as_advanced(CURL_DISABLE_GETOPTIONS)
+option(CURL_DISABLE_GOPHER "disables Gopher" OFF)
+mark_as_advanced(CURL_DISABLE_GOPHER)
+option(CURL_DISABLE_HSTS "disables HSTS support" OFF)
+mark_as_advanced(CURL_DISABLE_HSTS)
option(CURL_DISABLE_HTTP "disables HTTP" OFF)
mark_as_advanced(CURL_DISABLE_HTTP)
-
-option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF)
+option(CURL_DISABLE_HTTP_AUTH "disables all HTTP authentication methods" OFF)
+mark_as_advanced(CURL_DISABLE_HTTP_AUTH)
+option(CURL_DISABLE_IMAP "disables IMAP" OFF)
+mark_as_advanced(CURL_DISABLE_IMAP)
+option(CURL_DISABLE_LDAP "disables LDAP" OFF)
+mark_as_advanced(CURL_DISABLE_LDAP)
+option(CURL_DISABLE_LDAPS "disables LDAPS" OFF)
mark_as_advanced(CURL_DISABLE_LDAPS)
-
-option(CURL_DISABLE_RTSP "to disable RTSP" OFF)
-mark_as_advanced(CURL_DISABLE_RTSP)
-option(CURL_DISABLE_PROXY "to disable proxy" OFF)
-mark_as_advanced(CURL_DISABLE_PROXY)
-option(CURL_DISABLE_POP3 "to disable POP3" OFF)
+option(CURL_DISABLE_LIBCURL_OPTION "disables --libcurl option from the curl tool" OFF)
+mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION)
+option(CURL_DISABLE_MIME "disables MIME support" OFF)
+mark_as_advanced(CURL_DISABLE_MIME)
+option(CURL_DISABLE_MQTT "disables MQTT" OFF)
+mark_as_advanced(CURL_DISABLE_MQTT)
+option(CURL_DISABLE_NETRC "disables netrc parser" OFF)
+mark_as_advanced(CURL_DISABLE_NETRC)
+option(CURL_DISABLE_NTLM "disables NTLM support" OFF)
+mark_as_advanced(CURL_DISABLE_NTLM)
+option(CURL_DISABLE_PARSEDATE "disables date parsing" OFF)
+mark_as_advanced(CURL_DISABLE_PARSEDATE)
+option(CURL_DISABLE_POP3 "disables POP3" OFF)
mark_as_advanced(CURL_DISABLE_POP3)
-option(CURL_DISABLE_IMAP "to disable IMAP" OFF)
-mark_as_advanced(CURL_DISABLE_IMAP)
-option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
+option(CURL_DISABLE_PROGRESS_METER "disables built-in progress meter" OFF)
+mark_as_advanced(CURL_DISABLE_PROGRESS_METER)
+option(CURL_DISABLE_PROXY "disables proxy support" OFF)
+mark_as_advanced(CURL_DISABLE_PROXY)
+option(CURL_DISABLE_RTSP "disables RTSP" OFF)
+mark_as_advanced(CURL_DISABLE_RTSP)
+option(CURL_DISABLE_SHUFFLE_DNS "disables shuffle DNS feature" OFF)
+mark_as_advanced(CURL_DISABLE_SHUFFLE_DNS)
+option(CURL_DISABLE_SMB "disables SMB" OFF)
+mark_as_advanced(CURL_DISABLE_SMB)
+option(CURL_DISABLE_SMTP "disables SMTP" OFF)
mark_as_advanced(CURL_DISABLE_SMTP)
-option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
-mark_as_advanced(CURL_DISABLE_GOPHER)
-option(CURL_DISABLE_MQTT "to disable MQTT" OFF)
-mark_as_advanced(CURL_DISABLE_MQTT)
+option(CURL_DISABLE_SOCKETPAIR "disables use of socketpair for curl_multi_poll" OFF)
+mark_as_advanced(CURL_DISABLE_SOCKETPAIR)
+option(CURL_DISABLE_TELNET "disables Telnet" OFF)
+mark_as_advanced(CURL_DISABLE_TELNET)
+option(CURL_DISABLE_TFTP "disables TFTP" OFF)
+mark_as_advanced(CURL_DISABLE_TFTP)
+option(CURL_DISABLE_VERBOSE_STRINGS "disables verbose strings" OFF)
+mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
-option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON)
-mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
+# Corresponds to HTTP_ONLY in lib/curl_setup.h
+option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
+mark_as_advanced(HTTP_ONLY)
if(HTTP_ONLY)
set(CURL_DISABLE_DICT ON)
@@ -327,16 +373,6 @@ if(HTTP_ONLY)
set(CURL_DISABLE_TFTP ON)
endif()
-option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF)
-mark_as_advanced(CURL_DISABLE_ALTSVC)
-option(CURL_DISABLE_HSTS "to disable HSTS support" OFF)
-mark_as_advanced(CURL_DISABLE_HSTS)
-option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
-mark_as_advanced(CURL_DISABLE_COOKIES)
-option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
-mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
-option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
-mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
mark_as_advanced(ENABLE_IPV6)
if(ENABLE_IPV6 AND NOT WIN32)
@@ -495,28 +531,29 @@ if(CMAKE_USE_DARWINSSL)
message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.")
endif()
-if(CMAKE_USE_SECTRANSP)
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
if(NOT COREFOUNDATION_FRAMEWORK)
message(FATAL_ERROR "CoreFoundation framework not found")
endif()
- find_library(SECURITY_FRAMEWORK "Security")
- if(NOT SECURITY_FRAMEWORK)
- message(FATAL_ERROR "Security framework not found")
- endif()
-
- set(SSL_ENABLED ON)
- set(USE_SECTRANSP ON)
- list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
-endif()
-
-if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
message(FATAL_ERROR "SystemConfiguration framework not found")
endif()
- list(APPEND CURL_LIBS "${SYSTEMCONFIGURATION_FRAMEWORK}")
+
+ list(APPEND CURL_LIBS "-framework CoreFoundation" "-framework SystemConfiguration")
+
+ if(CMAKE_USE_SECTRANSP)
+ find_library(SECURITY_FRAMEWORK "Security")
+ if(NOT SECURITY_FRAMEWORK)
+ message(FATAL_ERROR "Security framework not found")
+ endif()
+
+ set(SSL_ENABLED ON)
+ set(USE_SECTRANSP ON)
+ list(APPEND CURL_LIBS "-framework Security")
+ endif()
endif()
if(CMAKE_USE_OPENSSL)
@@ -856,15 +893,6 @@ if(CMAKE_USE_LIBSSH2)
set(HAVE_LIBSSH2_H ON)
set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
-
- # now check for specific libssh2 symbols as they were added in different versions
- set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h")
- check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION)
- check_function_exists(libssh2_init HAVE_LIBSSH2_INIT)
- check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT)
- check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64)
- check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
- set(CMAKE_EXTRA_INCLUDE_FILES "")
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
endif()
@@ -947,7 +975,11 @@ endif()
option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON)
if(ENABLE_UNIX_SOCKETS)
include(CheckStructHasMember)
- check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
+ if(WIN32)
+ set(USE_UNIX_SOCKETS ON)
+ else()
+ check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
+ endif()
else()
unset(USE_UNIX_SOCKETS CACHE)
endif()
@@ -1065,8 +1097,6 @@ check_include_file_concat("alloca.h" HAVE_ALLOCA_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H)
check_include_file_concat("assert.h" HAVE_ASSERT_H)
-check_include_file_concat("crypto.h" HAVE_CRYPTO_H)
-check_include_file_concat("err.h" HAVE_ERR_H)
check_include_file_concat("errno.h" HAVE_ERRNO_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
@@ -1084,9 +1114,7 @@ check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
check_include_file_concat("pem.h" HAVE_PEM_H)
check_include_file_concat("poll.h" HAVE_POLL_H)
check_include_file_concat("pwd.h" HAVE_PWD_H)
-check_include_file_concat("rsa.h" HAVE_RSA_H)
check_include_file_concat("setjmp.h" HAVE_SETJMP_H)
-check_include_file_concat("sgtty.h" HAVE_SGTTY_H)
check_include_file_concat("signal.h" HAVE_SIGNAL_H)
check_include_file_concat("ssl.h" HAVE_SSL_H)
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
@@ -1149,12 +1177,8 @@ endif()
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
-check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
-check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR)
-check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA)
-check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
@@ -1179,11 +1203,8 @@ check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
-check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR)
-check_symbol_exists(fork "${CURL_INCLUDES}" HAVE_FORK)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO)
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
-check_symbol_exists(freeifaddrs "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
@@ -1250,12 +1271,6 @@ foreach(CURL_TEST
HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
TIME_WITH_SYS_TIME
HAVE_O_NONBLOCK
- HAVE_GETHOSTBYADDR_R_5
- HAVE_GETHOSTBYADDR_R_7
- HAVE_GETHOSTBYADDR_R_8
- HAVE_GETHOSTBYADDR_R_5_REENTRANT
- HAVE_GETHOSTBYADDR_R_7_REENTRANT
- HAVE_GETHOSTBYADDR_R_8_REENTRANT
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
HAVE_GETHOSTBYNAME_R_6
@@ -1265,8 +1280,6 @@ foreach(CURL_TEST
HAVE_IN_ADDR_T
HAVE_BOOL_T
STDC_HEADERS
- HAVE_INET_NTOA_R_DECL
- HAVE_INET_NTOA_R_DECL_REENTRANT
HAVE_GETADDRINFO
HAVE_FILE_OFFSET_BITS
HAVE_VARIADIC_MACROS_C99
@@ -1298,13 +1311,9 @@ endforeach()
# Check for reentrant
foreach(CURL_TEST
- HAVE_GETHOSTBYADDR_R_5
- HAVE_GETHOSTBYADDR_R_7
- HAVE_GETHOSTBYADDR_R_8
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
- HAVE_GETHOSTBYNAME_R_6
- HAVE_INET_NTOA_R_DECL_REENTRANT)
+ HAVE_GETHOSTBYNAME_R_6)
if(NOT ${CURL_TEST})
if(${CURL_TEST}_REENTRANT)
set(NEED_REENTRANT 1)
@@ -1314,9 +1323,6 @@ endforeach()
if(NEED_REENTRANT)
foreach(CURL_TEST
- HAVE_GETHOSTBYADDR_R_5
- HAVE_GETHOSTBYADDR_R_7
- HAVE_GETHOSTBYADDR_R_8
HAVE_GETHOSTBYNAME_R_3
HAVE_GETHOSTBYNAME_R_5
HAVE_GETHOSTBYNAME_R_6)
@@ -1327,11 +1333,6 @@ if(NEED_REENTRANT)
endforeach()
endif()
-if(HAVE_INET_NTOA_R_DECL_REENTRANT)
- set(HAVE_INET_NTOA_R_DECL 1)
- set(NEED_REENTRANT 1)
-endif()
-
# Check clock_gettime(CLOCK_MONOTONIC, x) support
curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
@@ -1527,8 +1528,8 @@ endmacro()
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_MBEDTLS OR
- USE_DARWINSSL OR USE_WIN32_CRYPTO))
+if(NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
+ (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO))
set(use_curl_ntlm_core ON)
endif()
@@ -1556,10 +1557,10 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-_add_if("NTLM" NOT CURL_DISABLE_CRYPTO_AUTH AND
+_add_if("NTLM" NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
# TODO missing option (autoconf: --enable-ntlm-wb)
-_add_if("NTLM_WB" NOT CURL_DISABLE_CRYPTO_AUTH AND
+_add_if("NTLM_WB" NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
(use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index 55a6a39c1..7b50b7c07 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -25,9 +25,6 @@
/*
* If you have libcurl problems, all docs and details are found here:
* https://curl.se/libcurl/
- *
- * curl-library mailing list subscription and unsubscription web interface:
- * https://cool.haxx.se/mailman/listinfo/curl-library/
*/
#ifdef CURL_NO_OLDIES
@@ -74,8 +71,9 @@
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
- defined(__CYGWIN__) || defined(AMIGA) || \
- (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
+ defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
+ (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
+ defined(__VXWORKS__)
#include <sys/select.h>
#endif
@@ -541,7 +539,7 @@ typedef enum {
CURLE_OBSOLETE46, /* 46 - NOT USED */
CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */
CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
- CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */
+ CURLE_SETOPT_OPTION_SYNTAX, /* 49 - Malformed setopt option */
CURLE_OBSOLETE50, /* 50 - NOT USED */
CURLE_OBSOLETE51, /* 51 - NOT USED */
CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
@@ -636,6 +634,9 @@ typedef enum {
/* The following were added in 7.21.5, April 2011 */
#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
+/* Added for 7.78.0 */
+#define CURLE_TELNET_OPTION_SYNTAX CURLE_SETOPT_OPTION_SYNTAX
+
/* The following were added in 7.17.1 */
/* These are scheduled to disappear by 2009 */
#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
@@ -2084,13 +2085,13 @@ typedef enum {
/* Parameters for V4 signature */
CURLOPT(CURLOPT_AWS_SIGV4, CURLOPTTYPE_STRINGPOINT, 305),
- /* Same as CURLOPT_SSL_VERIFYPEER but for DOH (DNS-over-HTTPS) servers. */
+ /* Same as CURLOPT_SSL_VERIFYPEER but for DoH (DNS-over-HTTPS) servers. */
CURLOPT(CURLOPT_DOH_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 306),
- /* Same as CURLOPT_SSL_VERIFYHOST but for DOH (DNS-over-HTTPS) servers. */
+ /* Same as CURLOPT_SSL_VERIFYHOST but for DoH (DNS-over-HTTPS) servers. */
CURLOPT(CURLOPT_DOH_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 307),
- /* Same as CURLOPT_SSL_VERIFYSTATUS but for DOH (DNS-over-HTTPS) servers. */
+ /* Same as CURLOPT_SSL_VERIFYSTATUS but for DoH (DNS-over-HTTPS) servers. */
CURLOPT(CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 308),
/* The CA certificates as "blob" used to validate the peer certificate
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index a8d5449af..9019868c0 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -30,13 +30,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.77.0"
+#define LIBCURL_VERSION "7.79.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 77
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 79
+#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x074d00
+#define LIBCURL_VERSION_NUM 0x074f01
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/urlapi.h b/Utilities/cmcurl/include/curl/urlapi.h
index 7343cb659..1d7088011 100644
--- a/Utilities/cmcurl/include/curl/urlapi.h
+++ b/Utilities/cmcurl/include/curl/urlapi.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,6 +79,7 @@ typedef enum {
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
+#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
typedef struct Curl_URL CURLU;
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index 4ab77fdfc..36acc3a5e 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -460,7 +460,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
(void)data;
#endif
if(result) {
- infof(data, "Excessive alt-svc header, ignoring...\n");
+ infof(data, "Excessive alt-svc header, ignoring.");
return CURLE_OK;
}
@@ -496,7 +496,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
p++;
len = p - hostp;
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
- infof(data, "Excessive alt-svc host name, ignoring...\n");
+ infof(data, "Excessive alt-svc host name, ignoring.");
dstalpnid = ALPN_none;
}
else {
@@ -513,7 +513,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
/* a port number */
unsigned long port = strtoul(++p, &end_ptr, 10);
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
- infof(data, "Unknown alt-svc port number, ignoring...\n");
+ infof(data, "Unknown alt-svc port number, ignoring.");
dstalpnid = ALPN_none;
}
p = end_ptr;
@@ -579,12 +579,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
as->expires = maxage + time(NULL);
as->persist = persist;
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
- infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+ infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
Curl_alpnid2str(dstalpnid));
}
}
else {
- infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n",
+ infof(data, "Unknown alt-svc protocol \"%s\", skipping.",
alpnbuf);
}
}
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 782784735..763a4aaa0 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -59,7 +59,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "multiif.h"
#include "inet_pton.h"
@@ -80,13 +79,33 @@
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
#endif
+#if ARES_VERSION >= 0x010601
+/* IPv6 supported since 1.6.1 */
+#define HAVE_CARES_IPV6 1
+#endif
+
+#if ARES_VERSION >= 0x010704
+#define HAVE_CARES_SERVERS_CSV 1
+#define HAVE_CARES_LOCAL_DEV 1
+#define HAVE_CARES_SET_LOCAL 1
+#endif
+
+#if ARES_VERSION >= 0x010b00
+#define HAVE_CARES_PORTS_CSV 1
+#endif
+
+#if ARES_VERSION >= 0x011000
+/* 1.16.0 or later has ares_getaddrinfo */
+#define HAVE_CARES_GETADDRINFO 1
+#endif
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
struct thread_data {
- int num_pending; /* number of ares_gethostbyname() requests */
+ int num_pending; /* number of outstanding c-ares requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
int last_status;
@@ -206,7 +225,8 @@ static void destroy_async_data(struct Curl_async *async);
*/
void Curl_resolver_cancel(struct Curl_easy *data)
{
- if(data && data->state.async.resolver)
+ DEBUGASSERT(data);
+ if(data->state.async.resolver)
ares_cancel((ares_channel)data->state.async.resolver);
destroy_async_data(&data->state.async);
}
@@ -489,21 +509,37 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
return result;
}
+#ifndef HAVE_CARES_GETADDRINFO
+
/* Connects results to the list */
static void compound_results(struct thread_data *res,
struct Curl_addrinfo *ai)
{
- struct Curl_addrinfo *ai_tail;
if(!ai)
return;
- ai_tail = ai;
- while(ai_tail->ai_next)
- ai_tail = ai_tail->ai_next;
+#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+ if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
+ /* We have results already, put the new IPv6 entries at the head of the
+ list. */
+ struct Curl_addrinfo *temp_ai_tail = res->temp_ai;
+
+ while(temp_ai_tail->ai_next)
+ temp_ai_tail = temp_ai_tail->ai_next;
- /* Add the new results to the list of old results. */
- ai_tail->ai_next = res->temp_ai;
- res->temp_ai = ai;
+ temp_ai_tail->ai_next = ai;
+ }
+ else
+#endif /* CURLRES_IPV6 */
+ {
+ /* Add the new results to the list of old results. */
+ struct Curl_addrinfo *ai_tail = ai;
+ while(ai_tail->ai_next)
+ ai_tail = ai_tail->ai_next;
+
+ ai_tail->ai_next = res->temp_ai;
+ res->temp_ai = ai;
+ }
}
/*
@@ -605,7 +641,98 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
}
}
}
+#else
+/* c-ares 1.16.0 or later */
+
+/*
+ * ares2addr() converts an address list provided by c-ares to an internal
+ * libcurl compatible list
+ */
+static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
+{
+ /* traverse the ares_addrinfo_node list */
+ struct ares_addrinfo_node *ai;
+ struct Curl_addrinfo *cafirst = NULL;
+ struct Curl_addrinfo *calast = NULL;
+ int error = 0;
+
+ for(ai = node; ai != NULL; ai = ai->ai_next) {
+ size_t ss_size;
+ struct Curl_addrinfo *ca;
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+#ifdef ENABLE_IPV6
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if(!ai->ai_addr || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
+
+ ca = malloc(sizeof(struct Curl_addrinfo) + ss_size);
+ if(!ca) {
+ error = EAI_MEMORY;
+ break;
+ }
+
+ /* copy each structure member individually, member ordering, */
+ /* size, or padding might be different for each platform. */
+
+ ca->ai_flags = ai->ai_flags;
+ ca->ai_family = ai->ai_family;
+ ca->ai_socktype = ai->ai_socktype;
+ ca->ai_protocol = ai->ai_protocol;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = NULL;
+ ca->ai_canonname = NULL;
+ ca->ai_next = NULL;
+
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+ /* if the return list is empty, this becomes the first element */
+ if(!cafirst)
+ cafirst = ca;
+
+ /* add this element last in the return list */
+ if(calast)
+ calast->ai_next = ca;
+ calast = ca;
+ }
+
+ /* if we failed, destroy the Curl_addrinfo list */
+ if(error) {
+ Curl_freeaddrinfo(cafirst);
+ cafirst = NULL;
+ }
+
+ return cafirst;
+}
+
+static void addrinfo_cb(void *arg, int status, int timeouts,
+ struct ares_addrinfo *result)
+{
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ struct thread_data *res = data->state.async.tdata;
+ (void)timeouts;
+ if(ARES_SUCCESS == status) {
+ res->temp_ai = ares2addr(result->nodes);
+ res->last_status = CURL_ASYNC_SUCCESS;
+ ares_freeaddrinfo(result);
+ }
+ res->num_pending--;
+}
+#endif
/*
* Curl_resolver_getaddrinfo() - when using ares
*
@@ -643,8 +770,28 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
-#if ARES_VERSION >= 0x010601
- /* IPv6 supported by c-ares since 1.6.1 */
+#ifdef HAVE_CARES_GETADDRINFO
+ {
+ struct ares_addrinfo_hints hints;
+ char service[12];
+ int pf = PF_INET;
+ memset(&hints, 0, sizeof(hints));
+#ifdef CURLRES_IPV6
+ if(Curl_ipv6works(data))
+ /* The stack seems to be IPv6-enabled */
+ pf = PF_UNSPEC;
+#endif /* CURLRES_IPV6 */
+ hints.ai_family = pf;
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
+ SOCK_STREAM : SOCK_DGRAM;
+ msnprintf(service, sizeof(service), "%d", port);
+ res->num_pending = 1;
+ ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
+ service, &hints, addrinfo_cb, data);
+ }
+#else
+
+#ifdef HAVE_CARES_IPV6
if(Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
@@ -656,7 +803,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
PF_INET6, query_completed_cb, data);
}
else
-#endif /* ARES_VERSION >= 0x010601 */
+#endif
{
res->num_pending = 1;
@@ -665,7 +812,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
hostname, PF_INET,
query_completed_cb, data);
}
-
+#endif
*waitp = 1; /* expect asynchronous response */
}
return NULL; /* no struct yet */
@@ -686,8 +833,8 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
if(!(servers && servers[0]))
return CURLE_OK;
-#if (ARES_VERSION >= 0x010704)
-#if (ARES_VERSION >= 0x010b00)
+#ifdef HAVE_CARES_SERVERS_CSV
+#ifdef HAVE_CARES_PORTS_CSV
ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
servers);
#else
@@ -717,7 +864,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
-#if (ARES_VERSION >= 0x010704)
+#ifdef HAVE_CARES_LOCAL_DEV
if(!interf)
interf = "";
@@ -734,7 +881,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
-#if (ARES_VERSION >= 0x010704)
+#ifdef HAVE_CARES_SET_LOCAL
struct in_addr a4;
if((!local_ip4) || (local_ip4[0] == 0)) {
@@ -760,7 +907,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
-#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)
+#if defined(HAVE_CARES_SET_LOCAL) && defined(ENABLE_IPV6)
unsigned char a6[INET6_ADDRSTRLEN];
if((!local_ip6) || (local_ip6[0] == 0)) {
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 36f68cb49..149172ad3 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -68,7 +68,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "multiif.h"
#include "inet_ntop.h"
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
index 81f589eb9..26635cdc1 100644
--- a/Utilities/cmcurl/lib/c-hyper.c
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -124,6 +124,17 @@ static int hyper_each_header(void *userdata,
size_t len;
char *headp;
CURLcode result;
+ int writetype;
+
+ if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
+ failf(data, "Too long response header");
+ data->state.hresult = CURLE_OUT_OF_MEMORY;
+ return HYPER_ITER_BREAK;
+ }
+
+ if(!data->req.bytecount)
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+
Curl_dyn_reset(&data->state.headerb);
if(name_len) {
if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
@@ -145,7 +156,10 @@ static int hyper_each_header(void *userdata,
Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
- result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, len);
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+ result = Curl_client_write(data, writetype, headp, len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
return HYPER_ITER_BREAK;
@@ -162,13 +176,43 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
size_t len = hyper_buf_len(chunk);
struct Curl_easy *data = (struct Curl_easy *)userdata;
struct SingleRequest *k = &data->req;
- CURLcode result;
+ CURLcode result = CURLE_OK;
if(0 == k->bodywrites++) {
bool done = FALSE;
- result = Curl_http_firstwrite(data, data->conn, &done);
+#if defined(USE_NTLM)
+ struct connectdata *conn = data->conn;
+ if(conn->bits.close &&
+ (((data->req.httpcode == 401) &&
+ (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
+ ((data->req.httpcode == 407) &&
+ (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
+ infof(data, "Connection closed while negotiating NTLM");
+ data->state.authproblem = TRUE;
+ Curl_safefree(data->req.newurl);
+ }
+#endif
+ if(data->state.expect100header) {
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
+ if(data->req.httpcode < 400) {
+ k->exp100 = EXP100_SEND_DATA;
+ if(data->hyp.exp100_waker) {
+ hyper_waker_wake(data->hyp.exp100_waker);
+ data->hyp.exp100_waker = NULL;
+ }
+ }
+ else { /* >= 4xx */
+ k->exp100 = EXP100_FAILED;
+ }
+ }
+ if(data->state.hconnect && (data->req.httpcode/100 != 2)) {
+ done = TRUE;
+ result = CURLE_OK;
+ }
+ else
+ result = Curl_http_firstwrite(data, data->conn, &done);
if(result || done) {
- infof(data, "Return early from hyper_body_chunk\n");
+ infof(data, "Return early from hyper_body_chunk");
data->state.hresult = result;
return HYPER_ITER_BREAK;
}
@@ -207,11 +251,15 @@ static CURLcode status_line(struct Curl_easy *data,
CURLcode result;
size_t len;
const char *vstr;
+ int writetype;
vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
(http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
conn->httpversion =
http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
(http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+ if(http_version == HYPER_HTTP_VERSION_1_0)
+ data->state.httpwant = CURL_HTTP_VERSION_1_0;
+
data->req.httpcode = http_status;
result = Curl_http_statusline(data, conn);
@@ -229,7 +277,10 @@ static CURLcode status_line(struct Curl_easy *data,
len = Curl_dyn_len(&data->state.headerb);
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
len);
- result = Curl_client_write(data, CLIENTWRITE_HEADER,
+ writetype = CLIENTWRITE_HEADER;
+ if(data->set.include_header)
+ writetype |= CLIENTWRITE_BODY;
+ result = Curl_client_write(data, writetype,
Curl_dyn_ptr(&data->state.headerb), len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
@@ -270,8 +321,25 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
const uint8_t *reasonp;
size_t reason_len;
CURLcode result = CURLE_OK;
+ struct SingleRequest *k = &data->req;
(void)conn;
+ if(k->exp100 > EXP100_SEND_DATA) {
+ struct curltime now = Curl_now();
+ timediff_t ms = Curl_timediff(now, k->start100);
+ if(ms >= data->set.expect_100_timeout) {
+ /* we've waited long enough, continue anyway */
+ k->exp100 = EXP100_SEND_DATA;
+ k->keepon |= KEEP_SEND;
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
+ infof(data, "Done waiting for 100-continue");
+ if(data->hyp.exp100_waker) {
+ hyper_waker_wake(data->hyp.exp100_waker);
+ data->hyp.exp100_waker = NULL;
+ }
+ }
+ }
+
if(select_res & CURL_CSELECT_IN) {
if(h->read_waker)
hyper_waker_wake(h->read_waker);
@@ -305,19 +373,22 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
hyper_task_free(task);
if(t == HYPER_TASK_ERROR) {
- hyper_code errnum = hyper_error_code(hypererr);
- if(errnum == HYPERE_ABORTED_BY_CALLBACK) {
+ if(data->state.hresult) {
/* override Hyper's view, might not even be an error */
result = data->state.hresult;
- infof(data, "hyperstream is done (by early callback)\n");
+ infof(data, "hyperstream is done (by early callback)");
}
else {
uint8_t errbuf[256];
size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
hyper_code code = hyper_error_code(hypererr);
failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
+ if(code == HYPERE_ABORTED_BY_CALLBACK)
+ result = CURLE_OK;
+ else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
result = CURLE_GOT_NOTHING;
+ else if(code == HYPERE_INVALID_PEER_MESSAGE)
+ result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
else
result = CURLE_RECV_ERROR;
}
@@ -328,10 +399,15 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
else if(h->endtask == task) {
/* end of transfer */
*done = TRUE;
- infof(data, "hyperstream is done!\n");
+ infof(data, "hyperstream is done!");
+ if(!k->bodywrites) {
+ /* hyper doesn't always call the body write callback */
+ bool stilldone;
+ result = Curl_http_firstwrite(data, data->conn, &stilldone);
+ }
break;
}
- else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) {
+ else if(t != HYPER_TASK_RESPONSE) {
*didwhat = KEEP_RECV;
break;
}
@@ -472,7 +548,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
(uint8_t *)v, vlen)) {
- failf(data, "hyper_headers_add host");
+ failf(data, "hyper refused to add header '%s'", line);
return CURLE_OUT_OF_MEMORY;
}
if(data->set.verbose) {
@@ -485,7 +561,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
free(ptr);
}
else
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
}
numh++;
n += linelen;
@@ -526,12 +602,32 @@ static int uploadpostfields(void *userdata, hyper_context *ctx,
{
struct Curl_easy *data = (struct Curl_easy *)userdata;
(void)ctx;
+ if(data->req.exp100 > EXP100_SEND_DATA) {
+ if(data->req.exp100 == EXP100_FAILED)
+ return HYPER_POLL_ERROR;
+
+ /* still waiting confirmation */
+ if(data->hyp.exp100_waker)
+ hyper_waker_free(data->hyp.exp100_waker);
+ data->hyp.exp100_waker = hyper_context_waker(ctx);
+ return HYPER_POLL_PENDING;
+ }
if(data->req.upload_done)
*chunk = NULL; /* nothing more to deliver */
else {
/* send everything off in a single go */
- *chunk = hyper_buf_copy(data->set.postfields,
- (size_t)data->req.p.http->postsize);
+ hyper_buf *copy = hyper_buf_copy(data->set.postfields,
+ (size_t)data->req.p.http->postsize);
+ if(copy)
+ *chunk = copy;
+ else {
+ data->state.hresult = CURLE_OUT_OF_MEMORY;
+ return HYPER_POLL_ERROR;
+ }
+ /* increasing the writebytecount here is a little premature but we
+ don't know exactly when the body is sent*/
+ data->req.writebytecount += (size_t)data->req.p.http->postsize;
+ Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
data->req.upload_done = TRUE;
}
return HYPER_POLL_READY;
@@ -542,16 +638,41 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
{
size_t fillcount;
struct Curl_easy *data = (struct Curl_easy *)userdata;
- CURLcode result =
- Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
+ CURLcode result;
(void)ctx;
- if(result)
+
+ if(data->req.exp100 > EXP100_SEND_DATA) {
+ if(data->req.exp100 == EXP100_FAILED)
+ return HYPER_POLL_ERROR;
+
+ /* still waiting confirmation */
+ if(data->hyp.exp100_waker)
+ hyper_waker_free(data->hyp.exp100_waker);
+ data->hyp.exp100_waker = hyper_context_waker(ctx);
+ return HYPER_POLL_PENDING;
+ }
+
+ result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
+ if(result) {
+ data->state.hresult = result;
return HYPER_POLL_ERROR;
+ }
if(!fillcount)
/* done! */
*chunk = NULL;
- else
- *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
+ else {
+ hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
+ if(copy)
+ *chunk = copy;
+ else {
+ data->state.hresult = CURLE_OUT_OF_MEMORY;
+ return HYPER_POLL_ERROR;
+ }
+ /* increasing the writebytecount here is a little premature but we
+ don't know exactly when the body is sent*/
+ data->req.writebytecount += fillcount;
+ Curl_pgrsSetUploadCounter(data, fillcount);
+ }
return HYPER_POLL_READY;
}
@@ -566,6 +687,7 @@ static CURLcode bodysend(struct Curl_easy *data,
hyper_request *hyperreq,
Curl_HttpReq httpreq)
{
+ struct HTTP *http = data->req.p.http;
CURLcode result = CURLE_OK;
struct dynbuf req;
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
@@ -598,6 +720,7 @@ static CURLcode bodysend(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
}
}
+ http->sending = HTTPSEND_BODY;
return result;
}
@@ -616,6 +739,48 @@ static CURLcode cookies(struct Curl_easy *data,
return result;
}
+/* called on 1xx responses */
+static void http1xx_cb(void *arg, struct hyper_response *resp)
+{
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ hyper_headers *headers = NULL;
+ CURLcode result = CURLE_OK;
+ uint16_t http_status;
+ int http_version;
+ const uint8_t *reasonp;
+ size_t reason_len;
+
+ infof(data, "Got HTTP 1xx informational");
+
+ http_status = hyper_response_status(resp);
+ http_version = hyper_response_version(resp);
+ reasonp = hyper_response_reason_phrase(resp);
+ reason_len = hyper_response_reason_phrase_len(resp);
+
+ result = status_line(data, data->conn,
+ http_status, http_version, reasonp, reason_len);
+ if(!result) {
+ headers = hyper_response_headers(resp);
+ if(!headers) {
+ failf(data, "hyperstream: couldn't get 1xx response headers");
+ result = CURLE_RECV_ERROR;
+ }
+ }
+ data->state.hresult = result;
+
+ if(!result) {
+ /* the headers are already received */
+ hyper_headers_foreach(headers, hyper_each_header, data);
+ /* this callback also sets data->state.hresult on error */
+
+ if(empty_header(data))
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->state.hresult)
+ infof(data, "ERROR in 1xx, bail out!");
+}
+
/*
* Curl_http() gets called from the generic multi_do() function when a HTTP
* request is to be performed. This creates and sends a properly constructed
@@ -633,20 +798,20 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
hyper_request *req = NULL;
hyper_headers *headers = NULL;
hyper_task *handshake = NULL;
- hyper_error *hypererr = NULL;
CURLcode result;
const char *p_accept; /* Accept: string */
const char *method;
Curl_HttpReq httpreq;
bool h2 = FALSE;
const char *te = NULL; /* transfer-encoding */
+ hyper_code rc;
/* Always consider the DO phase done after this function call, even if there
may be parts of the request that is not yet sent, since we can deal with
the rest of the request in the PERFORM phase. */
*done = TRUE;
- infof(data, "Time for the Hyper dance\n");
+ infof(data, "Time for the Hyper dance");
memset(h, 0, sizeof(struct hyptransfer));
result = Curl_http_host(data, conn);
@@ -743,7 +908,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
- if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+ if(!Curl_use_http_1_1plus(data, conn)) {
if(HYPERE_OK != hyper_request_set_version(req,
HYPER_HTTP_VERSION_1_0)) {
failf(data, "error setting HTTP version");
@@ -766,6 +931,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
+ rc = hyper_request_on_informational(req, http1xx_cb, data);
+ if(rc)
+ return CURLE_OUT_OF_MEMORY;
+
result = Curl_http_body(data, conn, httpreq, &te);
if(result)
return result;
@@ -830,6 +999,15 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
else
Curl_safefree(data->state.aptr.accept_encoding);
+#ifdef HAVE_LIBZ
+ /* we only consider transfer-encoding magic if libz support is built-in */
+ result = Curl_transferencode(data);
+ if(result)
+ return result;
+ if(Curl_hyper_header(data, headers, data->state.aptr.te))
+ goto error;
+#endif
+
result = cookies(data, conn, headers);
if(result)
return result;
@@ -862,25 +1040,21 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
hyper_clientconn_free(client);
- do {
- task = hyper_executor_poll(h->exec);
- if(task) {
- bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
- if(error)
- hypererr = hyper_task_value(task);
- hyper_task_free(task);
- if(error)
- goto error;
- }
- } while(task);
-
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
/* HTTP GET/HEAD download */
Curl_pgrsSetUploadSize(data, 0); /* nothing */
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
}
conn->datastream = Curl_hyper_stream;
-
+ if(data->state.expect100header)
+ /* Timeout count starts now since with Hyper we don't know exactly when
+ the full request has been sent. */
+ data->req.start100 = Curl_now();
+
+ /* clear userpwd and proxyuserpwd to avoid re-using old credentials
+ * from re-used connections */
+ Curl_safefree(data->state.aptr.userpwd);
+ Curl_safefree(data->state.aptr.proxyuserpwd);
return CURLE_OK;
error:
@@ -893,13 +1067,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(handshake)
hyper_task_free(handshake);
- if(hypererr) {
- uint8_t errbuf[256];
- size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
- hyper_code code = hyper_error_code(hypererr);
- failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- hyper_error_free(hypererr);
- }
return CURLE_OUT_OF_MEMORY;
}
@@ -918,6 +1085,10 @@ void Curl_hyper_done(struct Curl_easy *data)
hyper_waker_free(h->write_waker);
h->write_waker = NULL;
}
+ if(h->exp100_waker) {
+ hyper_waker_free(h->exp100_waker);
+ h->exp100_waker = NULL;
+ }
}
#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
diff --git a/Utilities/cmcurl/lib/c-hyper.h b/Utilities/cmcurl/lib/c-hyper.h
index d60ed78d1..d63defeff 100644
--- a/Utilities/cmcurl/lib/c-hyper.h
+++ b/Utilities/cmcurl/lib/c-hyper.h
@@ -33,6 +33,7 @@ struct hyptransfer {
hyper_waker *read_waker;
const hyper_executor *exec;
hyper_task *endtask;
+ hyper_waker *exp100_waker;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 5453c00f3..f5ba8ff70 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -34,6 +34,7 @@
#include "share.h"
#include "sigpipe.h"
#include "connect.h"
+#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -161,6 +162,7 @@ static void hashkey(struct connectdata *conn, char *buf,
/* put the number first so that the hostname gets cut off if too long */
msnprintf(buf, len, "%ld%s", port, hostname);
+ Curl_strntolower(buf, buf, len);
}
/* Returns number of connections currently held in the connection cache.
@@ -264,7 +266,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
connc->num_conn++;
DEBUGF(infof(data, "Added connection %ld. "
- "The cache now contains %zu members\n",
+ "The cache now contains %zu members",
conn->connection_id, connc->num_conn));
unlock:
@@ -298,7 +300,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
conn->bundle = NULL; /* removed from it */
if(connc) {
connc->num_conn--;
- DEBUGF(infof(data, "The cache now contains %zu members\n",
+ DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn));
}
if(lock) {
@@ -408,7 +410,7 @@ bool Curl_conncache_return_conn(struct Curl_easy *data,
conn->lastused = Curl_now(); /* it was used up until now */
if(maxconnects > 0 &&
Curl_conncache_size(data) > maxconnects) {
- infof(data, "Connection cache is full, closing the oldest one.\n");
+ infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) {
@@ -464,7 +466,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle, conn_candidate);
data->state.conn_cache->num_conn--;
- DEBUGF(infof(data, "The cache now contains %zu members\n",
+ DEBUGF(infof(data, "The cache now contains %zu members",
data->state.conn_cache->num_conn));
}
@@ -526,7 +528,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
/* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle_candidate, conn_candidate);
connc->num_conn--;
- DEBUGF(infof(data, "The cache now contains %zu members\n",
+ DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn));
}
CONNCACHE_UNLOCK(data);
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index d9317f378..d61b0374e 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -111,7 +111,7 @@ tcpkeepalive(struct Curl_easy *data,
/* only set IDLE and INTVL if setting KEEPALIVE is successful */
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
+ infof(data, "Failed to set SO_KEEPALIVE on fd %d", sockfd);
}
else {
#if defined(SIO_KEEPALIVE_VALS)
@@ -126,7 +126,7 @@ tcpkeepalive(struct Curl_easy *data,
vals.keepaliveinterval = optval;
if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
NULL, 0, &dummy, NULL, NULL) != 0) {
- infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
+ infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d",
(int)sockfd, WSAGetLastError());
}
#else
@@ -135,7 +135,7 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
+ infof(data, "Failed to set TCP_KEEPIDLE on fd %d", sockfd);
}
#endif
#ifdef TCP_KEEPINTVL
@@ -143,7 +143,7 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
+ infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd);
}
#endif
#ifdef TCP_KEEPALIVE
@@ -152,7 +152,7 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
+ infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd);
}
#endif
#endif
@@ -331,7 +331,7 @@ static CURLcode bindlocal(struct Curl_easy *data,
/*
* We now have the numerical IP address in the 'myhost' buffer
*/
- infof(data, "Local Interface %s is ip %s using address family %i\n",
+ infof(data, "Local Interface %s is ip %s using address family %i",
dev, myhost, af);
done = 1;
break;
@@ -364,7 +364,7 @@ static CURLcode bindlocal(struct Curl_easy *data,
if(h) {
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
Curl_printable_address(h->addr, myhost, sizeof(myhost));
- infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
+ infof(data, "Name '%s' family %i resolved to '%s' family %i",
dev, af, myhost, h->addr->ai_family);
Curl_resolv_unlock(data, h);
if(af != h->addr->ai_family) {
@@ -458,13 +458,13 @@ static CURLcode bindlocal(struct Curl_easy *data,
error, Curl_strerror(error, buffer, sizeof(buffer)));
return CURLE_INTERFACE_FAILED;
}
- infof(data, "Local port: %hu\n", port);
+ infof(data, "Local port: %hu", port);
conn->bits.bound = TRUE;
return CURLE_OK;
}
if(--portnum > 0) {
- infof(data, "Bind to local port %hu failed, trying next\n", port);
+ infof(data, "Bind to local port %hu failed, trying next", port);
port++; /* try next port */
/* We re-use/clobber the port variable here below */
if(sock->sa_family == AF_INET)
@@ -589,12 +589,10 @@ static CURLcode trynextip(struct Curl_easy *data,
struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
while(ai) {
- if(ai) {
- result = singleipconnect(data, conn, ai, tempindex);
- if(result == CURLE_COULDNT_CONNECT) {
- ai = ainext(conn, tempindex, TRUE);
- continue;
- }
+ result = singleipconnect(data, conn, ai, tempindex);
+ if(result == CURLE_COULDNT_CONNECT) {
+ ai = ainext(conn, tempindex, TRUE);
+ continue;
}
break;
}
@@ -753,10 +751,9 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
int local_port = -1;
if(conn->transport == TRNSPRT_TCP) {
- if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+ if(!conn->bits.reuse && !conn->bits.tcp_fastopen)
Curl_conninfo_remote(data, conn, sockfd);
- Curl_conninfo_local(data, sockfd, local_ip, &local_port);
- }
+ Curl_conninfo_local(data, sockfd, local_ip, &local_port);
} /* end of TCP-only section */
/* persist connection info in session handle */
@@ -872,15 +869,6 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
now = Curl_now();
- /* figure out how long time we have left to connect */
- allow = Curl_timeleft(data, &now, TRUE);
-
- if(allow < 0) {
- /* time-out, bail out, go home */
- failf(data, "Connection time-out");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
if(SOCKS_STATE(conn->cnnct.state)) {
/* still doing SOCKS */
result = connect_SOCKS(data, sockindex, connected);
@@ -930,7 +918,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
if(Curl_timediff(now, conn->connecttime) >=
conn->timeoutms_per_addr[i]) {
infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
- "ms connect time, move on!\n", conn->timeoutms_per_addr[i]);
+ "ms connect time, move on!", conn->timeoutms_per_addr[i]);
error = ETIMEDOUT;
}
@@ -989,11 +977,12 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
char buffer[STRERROR_LEN];
Curl_printable_address(conn->tempaddr[i], ipaddress,
sizeof(ipaddress));
- infof(data, "connect to %s port %ld failed: %s\n",
+ infof(data, "connect to %s port %u failed: %s",
ipaddress, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
#endif
+ allow = Curl_timeleft(data, &now, TRUE);
conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
ainext(conn, i, TRUE);
@@ -1006,6 +995,21 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
}
}
+ /*
+ * Now that we've checked whether we are connected, check whether we've
+ * already timed out.
+ *
+ * First figure out how long time we have left to connect */
+
+ allow = Curl_timeleft(data, &now, TRUE);
+
+ if(allow < 0) {
+ /* time-out, bail out, go home */
+ failf(data, "Connection timeout after %ld ms",
+ Curl_timediff(now, data->progress.t_startsingle));
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
if(result &&
(conn->tempsock[0] == CURL_SOCKET_BAD) &&
(conn->tempsock[1] == CURL_SOCKET_BAD)) {
@@ -1031,9 +1035,11 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
else
hostname = conn->host.name;
- failf(data, "Failed to connect to %s port %ld: %s",
- hostname, conn->port,
- Curl_strerror(error, buffer, sizeof(buffer)));
+ failf(data, "Failed to connect to %s port %u after "
+ "%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
+ hostname, conn->port,
+ Curl_timediff(now, data->progress.t_startsingle),
+ Curl_strerror(error, buffer, sizeof(buffer)));
Curl_quic_disconnect(data, conn, 0);
Curl_quic_disconnect(data, conn, 1);
@@ -1065,7 +1071,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
- infof(data, "Could not set TCP_NODELAY: %s\n",
+ infof(data, "Could not set TCP_NODELAY: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
#else
(void)data;
@@ -1084,9 +1090,11 @@ static void nosigpipe(struct Curl_easy *data,
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
- infof(data, "Could not set SO_NOSIGPIPE: %s\n",
+ infof(data, "Could not set SO_NOSIGPIPE: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+#endif
}
}
#else
@@ -1180,7 +1188,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
Curl_closesocket(data, conn, sockfd);
return CURLE_OK;
}
- infof(data, " Trying %s:%d...\n", ipaddress, port);
+ infof(data, " Trying %s:%d...", ipaddress, port);
#ifdef ENABLE_IPV6
is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1271,7 +1279,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
(void *)&optval, sizeof(optval)) < 0)
- infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
+ infof(data, "Failed to enable TCP Fast Open on fd %d", sockfd);
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
#elif defined(MSG_FASTOPEN) /* old Linux */
@@ -1321,7 +1329,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
default:
/* unknown error, fallthrough and try another address! */
- infof(data, "Immediate connect fail for %s: %s\n",
+ infof(data, "Immediate connect fail for %s: %s",
ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
data->state.os_errno = error;
@@ -1394,7 +1402,7 @@ CURLcode Curl_connecthost(struct Curl_easy *data,
ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
- DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
+ DEBUGF(infof(data, "family0 == %s, family1 == %s",
conn->tempfamily[0] == AF_INET ? "v4" : "v6",
conn->tempfamily[1] == AF_INET ? "v4" : "v6"));
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 941623f9d..b7531f742 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -95,7 +95,6 @@ Example set of cookies:
#include "strcase.h"
#include "curl_get_line.h"
#include "curl_memrchr.h"
-#include "inet_pton.h"
#include "parsedate.h"
#include "rand.h"
#include "rename.h"
@@ -147,31 +146,6 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
}
/*
- * isip
- *
- * Returns true if the given string is an IPv4 or IPv6 address (if IPv6 has
- * been enabled while building libcurl, and false otherwise.
- */
-static bool isip(const char *domain)
-{
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
-
- if(Curl_inet_pton(AF_INET, domain, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, domain, &addr6)
-#endif
- ) {
- /* domain name given as IP address */
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
@@ -303,7 +277,7 @@ static size_t cookiehash(const char * const domain)
const char *top;
size_t len;
- if(!domain || isip(domain))
+ if(!domain || Curl_host_is_ipnum(domain))
return 0;
top = get_top_domain(domain, &len);
@@ -366,7 +340,7 @@ void Curl_cookie_loadfiles(struct Curl_easy *data)
* Failure may be due to OOM or a bad cookie; both are ignored
* but only the first should be
*/
- infof(data, "ignoring failed cookie_init for %s\n", list->data);
+ infof(data, "ignoring failed cookie_init for %s", list->data);
else
data->cookies = newcookies;
list = list->next;
@@ -397,7 +371,9 @@ static void strstore(char **str, const char *newstr)
*
* Remove expired cookies from the hash by inspecting the expires timestamp on
* each cookie in the hash, freeing and deleting any where the timestamp is in
- * the past.
+ * the past. If the cookiejar has recorded the next timestamp at which one or
+ * more cookies expire, then processing will exit early in case this timestamp
+ * is in the future.
*/
static void remove_expired(struct CookieInfo *cookies)
{
@@ -405,6 +381,20 @@ static void remove_expired(struct CookieInfo *cookies)
curl_off_t now = (curl_off_t)time(NULL);
unsigned int i;
+ /*
+ * If the earliest expiration timestamp in the jar is in the future we can
+ * skip scanning the whole jar and instead exit early as there won't be any
+ * cookies to evict. If we need to evict however, reset the next_expiration
+ * counter in order to track the next one. In case the recorded first
+ * expiration is the max offset, then perform the safe fallback of checking
+ * all cookies.
+ */
+ if(now < cookies->next_expiration &&
+ cookies->next_expiration != CURL_OFF_T_MAX)
+ return;
+ else
+ cookies->next_expiration = CURL_OFF_T_MAX;
+
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
struct Cookie *pv = NULL;
co = cookies->cookies[i];
@@ -421,6 +411,12 @@ static void remove_expired(struct CookieInfo *cookies)
freecookie(co);
}
else {
+ /*
+ * If this cookie has an expiration timestamp earlier than what we've
+ * seen so far then record it for the next round of expirations.
+ */
+ if(co->expires && co->expires < cookies->next_expiration)
+ cookies->next_expiration = co->expires;
pv = co;
}
co = nx;
@@ -524,7 +520,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
((nlen + len) > MAX_NAME)) {
freecookie(co);
- infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
+ infof(data, "oversized cookie dropped, name/val %zu + %zu bytes",
nlen, len);
return NULL;
}
@@ -645,7 +641,7 @@ Curl_cookie_add(struct Curl_easy *data,
domain = ":";
#endif
- is_ip = isip(domain ? domain : whatptr);
+ is_ip = Curl_host_is_ipnum(domain ? domain : whatptr);
if(!domain
|| (is_ip && !strcmp(whatptr, domain))
@@ -665,7 +661,7 @@ Curl_cookie_add(struct Curl_easy *data,
* not a domain to which the current host belongs. Mark as bad.
*/
badcookie = TRUE;
- infof(data, "skipped cookie with bad tailmatch domain: %s\n",
+ infof(data, "skipped cookie with bad tailmatch domain: %s",
whatptr);
}
}
@@ -996,7 +992,7 @@ Curl_cookie_add(struct Curl_easy *data,
* must also check that the data handle isn't NULL since the psl code will
* dereference it.
*/
- if(data && (domain && co->domain && !isip(co->domain))) {
+ if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
const psl_ctx_t *psl = Curl_psl_use(data);
int acceptable;
@@ -1009,7 +1005,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "
- "set cookies for '%s'\n", co->name, domain, co->domain);
+ "set cookies for '%s'", co->name, domain, co->domain);
freecookie(co);
return NULL;
}
@@ -1121,7 +1117,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(c->running)
/* Only show this when NOT reading the cookies from a file */
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
- "expire %" CURL_FORMAT_CURL_OFF_T "\n",
+ "expire %" CURL_FORMAT_CURL_OFF_T,
replace_old?"Replaced":"Added", co->name, co->value,
co->domain, co->path, co->expires);
@@ -1134,6 +1130,13 @@ Curl_cookie_add(struct Curl_easy *data,
c->numcookies++; /* one more cookie in the jar */
}
+ /*
+ * Now that we've added a new cookie to the jar, update the expiration
+ * tracker in case it is the next one to expire.
+ */
+ if(co->expires && (co->expires < c->next_expiration))
+ c->next_expiration = co->expires;
+
return co;
}
@@ -1169,6 +1172,11 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
c->filename = strdup(file?file:"none"); /* copy the name just in case */
if(!c->filename)
goto fail; /* failed to get memory */
+ /*
+ * Initialize the next_expiration time to signal that we don't have enough
+ * information yet.
+ */
+ c->next_expiration = CURL_OFF_T_MAX;
}
else {
/* we got an already existing one, use that */
@@ -1215,7 +1223,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
/*
* Remove expired cookies from the hash. We must make sure to run this
- * after reading the file, and not not on every cookie.
+ * after reading the file, and not on every cookie.
*/
remove_expired(c);
@@ -1247,7 +1255,8 @@ fail:
*
* Helper function to sort cookies such that the longest path gets before the
* shorter path. Path, domain and name lengths are considered in that order,
- * with tge creationtime as the tiebreaker.
+ * with the creationtime as the tiebreaker. The creationtime is guaranteed to
+ * be unique per cookie, so we know we will get an ordering at that point.
*/
static int cookie_sort(const void *p1, const void *p2)
{
@@ -1355,7 +1364,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
remove_expired(c);
/* check if host is an IP(v4|v6) address */
- is_ip = isip(host);
+ is_ip = Curl_host_is_ipnum(host);
co = c->cookies[myhash];
@@ -1734,7 +1743,7 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
/* if we have a destination file for all the cookies to get dumped to */
res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]);
if(res)
- infof(data, "WARNING: failed to save cookies in %s: %s\n",
+ infof(data, "WARNING: failed to save cookies in %s: %s",
data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res));
}
else {
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index 460bbb104..0ffe08e63 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -65,6 +65,7 @@ struct CookieInfo {
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
int lastct; /* last creation-time used in the jar */
+ curl_off_t next_expiration; /* the next time at which expiration happens */
};
/* This is the maximum line length we accept for a cookie line. RFC 2109
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index 1d5067bc0..842fd7fe2 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -50,12 +50,6 @@
# define in_addr_t unsigned long
#endif
-#if defined(USE_UNIX_SOCKETS) && defined(WINAPI_FAMILY) && \
- (WINAPI_FAMILY == WINAPI_FAMILY_APP)
- /* Required for sockaddr_un type */
-# include <afunix.h>
-#endif
-
#include <stddef.h>
#include "curl_addrinfo.h"
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 4fdc672a0..de035507e 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -26,61 +26,91 @@
/* when building libcurl itself */
#cmakedefine BUILDING_LIBCURL 1
-/* to disable cookies support */
+/* to disable alt-svc */
+#cmakedefine CURL_DISABLE_ALTSVC 1
+
+/* disables cookies support */
#cmakedefine CURL_DISABLE_COOKIES 1
-/* to disable cryptographic authentication */
+/* disables cryptographic authentication */
#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
-/* to disable DICT */
+/* disables DICT */
#cmakedefine CURL_DISABLE_DICT 1
-/* to disable FILE */
+/* disables DNS-over-HTTPS */
+#cmakedefine CURL_DISABLE_DOH 1
+
+/* disables FILE */
#cmakedefine CURL_DISABLE_FILE 1
-/* to disable FTP */
+/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
-/* to disable GOPHER */
+/* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1
-/* to disable IMAP */
-#cmakedefine CURL_DISABLE_IMAP 1
+/* disables HSTS support */
+#cmakedefine CURL_DISABLE_HSTS 1
-/* to disable HTTP */
+/* disables HTTP */
#cmakedefine CURL_DISABLE_HTTP 1
-/* to disable LDAP */
+/* disables IMAP */
+#cmakedefine CURL_DISABLE_IMAP 1
+
+/* disables LDAP */
#cmakedefine CURL_DISABLE_LDAP 1
-/* to disable LDAPS */
+/* disables LDAPS */
#cmakedefine CURL_DISABLE_LDAPS 1
-/* to disable MQTT */
+/* disables --libcurl option from the curl tool */
+#cmakedefine CURL_DISABLE_LIBCURL_OPTION 1
+
+/* disables MIME support */
+#cmakedefine CURL_DISABLE_MIME 1
+
+/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
-/* to disable POP3 */
+/* disables netrc parser */
+#cmakedefine CURL_DISABLE_NETRC 1
+
+/* disables NTLM support */
+#cmakedefine CURL_DISABLE_NTLM 1
+
+/* disables date parsing */
+#cmakedefine CURL_DISABLE_PARSEDATE 1
+
+/* disables POP3 */
#cmakedefine CURL_DISABLE_POP3 1
-/* to disable proxies */
+/* disables built-in progress meter */
+#cmakedefine CURL_DISABLE_PROGRESS_METER 1
+
+/* disables proxies */
#cmakedefine CURL_DISABLE_PROXY 1
-/* to disable RTSP */
+/* disables RTSP */
#cmakedefine CURL_DISABLE_RTSP 1
-/* to disable SMB */
+/* disables SMB */
#cmakedefine CURL_DISABLE_SMB 1
-/* to disable SMTP */
+/* disables SMTP */
#cmakedefine CURL_DISABLE_SMTP 1
-/* to disable TELNET */
+/* disables use of socketpair for curl_multi_poll */
+#cmakedefine CURL_DISABLE_SOCKETPAIR 1
+
+/* disables TELNET */
#cmakedefine CURL_DISABLE_TELNET 1
-/* to disable TFTP */
+/* disables TFTP */
#cmakedefine CURL_DISABLE_TFTP 1
-/* to disable verbose strings */
+/* disables verbose strings */
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
/* to make a symbol visible */
@@ -105,12 +135,6 @@
/* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 1
-/* Specifies the number of arguments to getservbyport_r */
-#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
-
-/* Specifies the size of the buffer to pass to getservbyport_r */
-#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE}
-
/* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1
@@ -144,18 +168,12 @@
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-/* Define to 1 if you have the <crypto.h> header file. */
-#cmakedefine HAVE_CRYPTO_H 1
-
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H 1
-/* Define to 1 if you have the <err.h> header file. */
-#cmakedefine HAVE_ERR_H 1
-
/* Define to 1 if you have the fcntl function. */
#cmakedefine HAVE_FCNTL 1
@@ -165,18 +183,9 @@
/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
#cmakedefine HAVE_FCNTL_O_NONBLOCK 1
-/* Define to 1 if you have the fdopen function. */
-#cmakedefine HAVE_FDOPEN 1
-
-/* Define to 1 if you have the `fork' function. */
-#cmakedefine HAVE_FORK 1
-
/* Define to 1 if you have the freeaddrinfo function. */
#cmakedefine HAVE_FREEADDRINFO 1
-/* Define to 1 if you have the freeifaddrs function. */
-#cmakedefine HAVE_FREEIFADDRS 1
-
/* Define to 1 if you have the ftruncate function. */
#cmakedefine HAVE_FTRUNCATE 1
@@ -189,21 +198,6 @@
/* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1
-/* Define to 1 if you have the gethostbyaddr function. */
-#cmakedefine HAVE_GETHOSTBYADDR 1
-
-/* Define to 1 if you have the gethostbyaddr_r function. */
-#cmakedefine HAVE_GETHOSTBYADDR_R 1
-
-/* gethostbyaddr_r() takes 5 args */
-#cmakedefine HAVE_GETHOSTBYADDR_R_5 1
-
-/* gethostbyaddr_r() takes 7 args */
-#cmakedefine HAVE_GETHOSTBYADDR_R_7 1
-
-/* gethostbyaddr_r() takes 8 args */
-#cmakedefine HAVE_GETHOSTBYADDR_R_8 1
-
/* Define to 1 if you have the gethostbyname function. */
#cmakedefine HAVE_GETHOSTBYNAME 1
@@ -252,9 +246,6 @@
/* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT 1
-/* Define to 1 if you have the getservbyport_r function. */
-#cmakedefine HAVE_GETSERVBYPORT_R 1
-
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY 1
@@ -388,21 +379,6 @@
/* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 1
-/* Define to 1 if libssh2 provides `libssh2_version'. */
-#cmakedefine HAVE_LIBSSH2_VERSION 1
-
-/* Define to 1 if libssh2 provides `libssh2_init'. */
-#cmakedefine HAVE_LIBSSH2_INIT 1
-
-/* Define to 1 if libssh2 provides `libssh2_exit'. */
-#cmakedefine HAVE_LIBSSH2_EXIT 1
-
-/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */
-#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1
-
-/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */
-#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1
-
/* Define to 1 if you have the <libssh2.h> header file. */
#cmakedefine HAVE_LIBSSH2_H 1
@@ -519,9 +495,6 @@
/* Define to 1 if you have the recvfrom function. */
#cmakedefine HAVE_RECVFROM 1
-/* Define to 1 if you have the <rsa.h> header file. */
-#cmakedefine HAVE_RSA_H 1
-
/* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1
@@ -555,9 +528,6 @@
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
-/* Define to 1 if you have the <sgtty.h> header file. */
-#cmakedefine HAVE_SGTTY_H 1
-
/* Define to 1 if you have the sigaction function. */
#cmakedefine HAVE_SIGACTION 1
@@ -573,12 +543,6 @@
/* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1
-/* Define to 1 if sig_atomic_t is an available typedef. */
-#cmakedefine HAVE_SIG_ATOMIC_T 1
-
-/* Define to 1 if sig_atomic_t is already defined as volatile. */
-#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1
-
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -994,9 +958,6 @@ ${SIZEOF_TIME_T_CODE}
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
-/* to disable alt-svc */
-#cmakedefine CURL_DISABLE_ALTSVC 1
-
/* to enable SSPI support */
#cmakedefine USE_WINDOWS_SSPI 1
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index b6f107e10..ecde74bfb 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -80,45 +80,3 @@ unsigned short Curl_read16_be(const unsigned char *buf)
return (unsigned short)(((unsigned short)buf[0] << 8) |
((unsigned short)buf[1]));
}
-
-#if (SIZEOF_CURL_OFF_T > 4)
-/*
- * write32_le()
- *
- * This function converts a 32-bit integer from the native endian format,
- * to little endian format ready for sending down the wire.
- *
- * Parameters:
- *
- * value [in] - The 32-bit integer value.
- * buffer [in] - A pointer to the output buffer.
- */
-static void write32_le(const int value, unsigned char *buffer)
-{
- buffer[0] = (char)(value & 0x000000FF);
- buffer[1] = (char)((value & 0x0000FF00) >> 8);
- buffer[2] = (char)((value & 0x00FF0000) >> 16);
- buffer[3] = (char)((value & 0xFF000000) >> 24);
-}
-
-/*
- * Curl_write64_le()
- *
- * This function converts a 64-bit integer from the native endian format,
- * to little endian format ready for sending down the wire.
- *
- * Parameters:
- *
- * value [in] - The 64-bit integer value.
- * buffer [in] - A pointer to the output buffer.
- */
-#if defined(HAVE_LONGLONG)
-void Curl_write64_le(const long long value, unsigned char *buffer)
-#else
-void Curl_write64_le(const __int64 value, unsigned char *buffer)
-#endif
-{
- write32_le((int)value, buffer);
- write32_le((int)(value >> 32), buffer + 4);
-}
-#endif /* SIZEOF_CURL_OFF_T > 4 */
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index acaaa1c68..5810dad14 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -59,7 +59,7 @@ OM_uint32 Curl_gss_init_sec_context(
req_flags |= GSS_C_DELEG_POLICY_FLAG;
#else
infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
- "compiled in\n");
+ "compiled in");
#endif
}
@@ -130,7 +130,7 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
- infof(data, "%s%s\n", prefix, buf);
+ infof(data, "%s%s", prefix, buf);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
(void)prefix;
diff --git a/Utilities/cmcurl/lib/curl_multibyte.c b/Utilities/cmcurl/lib/curl_multibyte.c
index 16418bee4..e9d2a8cb8 100644
--- a/Utilities/cmcurl/lib/curl_multibyte.c
+++ b/Utilities/cmcurl/lib/curl_multibyte.c
@@ -102,14 +102,16 @@ int curlx_win32_open(const char *filename, int oflag, ...)
va_end(param);
#ifdef _UNICODE
- if(filename_w)
+ if(filename_w) {
result = _wopen(filename_w, oflag, pmode);
- free(filename_w);
- if(result != -1)
- return result;
-#endif
-
+ free(filename_w);
+ }
+ else
+ errno = EINVAL;
+ return result;
+#else
return (_open)(filename, oflag, pmode);
+#endif
}
FILE *curlx_win32_fopen(const char *filename, const char *mode)
@@ -120,19 +122,20 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode)
wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
if(filename_w && mode_w)
result = _wfopen(filename_w, mode_w);
+ else
+ errno = EINVAL;
free(filename_w);
free(mode_w);
- if(result)
- return result;
-#endif
-
+ return result;
+#else
return (fopen)(filename, mode);
+#endif
}
int curlx_win32_stat(const char *path, struct_stat *buffer)
{
- int result = -1;
#ifdef _UNICODE
+ int result = -1;
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
#if defined(USE_WIN32_SMALL_FILES)
@@ -141,31 +144,34 @@ int curlx_win32_stat(const char *path, struct_stat *buffer)
result = _wstati64(path_w, buffer);
#endif
free(path_w);
- if(result != -1)
- return result;
}
-#endif /* _UNICODE */
-
+ else
+ errno = EINVAL;
+ return result;
+#else
#if defined(USE_WIN32_SMALL_FILES)
- result = _stat(path, buffer);
+ return _stat(path, buffer);
#else
- result = _stati64(path, buffer);
+ return _stati64(path, buffer);
+#endif
#endif
- return result;
}
int curlx_win32_access(const char *path, int mode)
{
#if defined(_UNICODE)
+ int result = -1;
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
- int result = _waccess(path_w, mode);
+ result = _waccess(path_w, mode);
free(path_w);
- if(result != -1)
- return result;
}
-#endif /* _UNICODE */
+ else
+ errno = EINVAL;
+ return result;
+#else
return _access(path, mode);
+#endif
}
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index 89d4ec872..749b44e4a 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -86,7 +86,6 @@
#elif defined(USE_MBEDTLS)
# include <mbedtls/des.h>
-# include "curl_md4.h"
#elif defined(USE_SECTRANSP)
@@ -498,17 +497,14 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
* network encoding not the host encoding.
*/
result = Curl_convert_to_network(data, (char *)pw, len * 2);
- if(result)
- return result;
-
- /* Create NT hashed password. */
- Curl_md4it(ntbuffer, pw, 2 * len);
-
- memset(ntbuffer + 16, 0, 21 - 16);
-
+ if(!result) {
+ /* Create NT hashed password. */
+ Curl_md4it(ntbuffer, pw, 2 * len);
+ memset(ntbuffer + 16, 0, 21 - 16);
+ }
free(pw);
- return CURLE_OK;
+ return result;
}
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 9af79fd66..5a3bc3c89 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -355,17 +355,17 @@ CURLcode Curl_input_ntlm_wb(struct Curl_easy *data,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted");
Curl_http_auth_cleanup_ntlm_wb(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected");
Curl_http_auth_cleanup_ntlm_wb(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)");
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -426,7 +426,8 @@ CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
/* Use Samba's 'winbind' daemon to support NTLM authentication,
* by delegating the NTLM challenge/response protocol to a helper
* in ntlm_auth.
- * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
+ * https://web.archive.org/web/20190925164737
+ * /devel.squid-cache.org/ntlm/squid_helper_protocol.html
* https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
* https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html
* Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
index f7fb7c082..24bdb3052 100644
--- a/Utilities/cmcurl/lib/curl_range.c
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -53,14 +53,14 @@ CURLcode Curl_range(struct Curl_easy *data)
if((to_t == CURL_OFFT_INVAL) && !from_t) {
/* X - */
data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file",
from));
}
else if((from_t == CURL_OFFT_INVAL) && !to_t) {
/* -Y */
data->req.maxdownload = to;
data->state.resume_from = -to;
- DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes",
to));
}
else {
@@ -78,12 +78,12 @@ CURLcode Curl_range(struct Curl_easy *data)
data->req.maxdownload = totalsize + 1; /* include last byte */
data->state.resume_from = from;
DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes",
from, data->req.maxdownload));
}
DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
" to %" CURL_FORMAT_CURL_OFF_T ", totally %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
+ CURL_FORMAT_CURL_OFF_T " bytes",
from, to, data->req.maxdownload));
}
else
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index a4d1059cb..4a2488720 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -234,7 +234,7 @@ static void state(struct SASL *sasl, struct Curl_easy *data,
};
if(sasl->state != newstate)
- infof(data, "SASL %p state change from %s to %s\n",
+ infof(data, "SASL %p state change from %s to %s",
(void *)sasl, names[sasl->state], names[newstate]);
#else
(void) data;
@@ -630,7 +630,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
}
else
/* Decode the security challenge and create the response message */
- result = Curl_auth_create_gssapi_security_message(data, &serverdata,
+ result = Curl_auth_create_gssapi_security_message(data,
+ conn->sasl_authzid,
+ &serverdata,
&conn->krb5,
&resp);
}
@@ -639,7 +641,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
/* Decode the security challenge and create the response message */
result = get_server_message(sasl, data, &serverdata);
if(!result)
- result = Curl_auth_create_gssapi_security_message(data, &serverdata,
+ result = Curl_auth_create_gssapi_security_message(data,
+ conn->sasl_authzid,
+ &serverdata,
&conn->krb5,
&resp);
break;
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 2d13a40a5..554dcc1e6 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -170,41 +170,47 @@
*/
#ifdef HTTP_ONLY
-# ifndef CURL_DISABLE_TFTP
-# define CURL_DISABLE_TFTP
+# ifndef CURL_DISABLE_DICT
+# define CURL_DISABLE_DICT
+# endif
+# ifndef CURL_DISABLE_FILE
+# define CURL_DISABLE_FILE
# endif
# ifndef CURL_DISABLE_FTP
# define CURL_DISABLE_FTP
# endif
+# ifndef CURL_DISABLE_GOPHER
+# define CURL_DISABLE_GOPHER
+# endif
+# ifndef CURL_DISABLE_IMAP
+# define CURL_DISABLE_IMAP
+# endif
# ifndef CURL_DISABLE_LDAP
# define CURL_DISABLE_LDAP
# endif
-# ifndef CURL_DISABLE_TELNET
-# define CURL_DISABLE_TELNET
+# ifndef CURL_DISABLE_LDAPS
+# define CURL_DISABLE_LDAPS
# endif
-# ifndef CURL_DISABLE_DICT
-# define CURL_DISABLE_DICT
+# ifndef CURL_DISABLE_MQTT
+# define CURL_DISABLE_MQTT
# endif
-# ifndef CURL_DISABLE_FILE
-# define CURL_DISABLE_FILE
+# ifndef CURL_DISABLE_POP3
+# define CURL_DISABLE_POP3
# endif
# ifndef CURL_DISABLE_RTSP
# define CURL_DISABLE_RTSP
# endif
-# ifndef CURL_DISABLE_POP3
-# define CURL_DISABLE_POP3
-# endif
-# ifndef CURL_DISABLE_IMAP
-# define CURL_DISABLE_IMAP
+# ifndef CURL_DISABLE_SMB
+# define CURL_DISABLE_SMB
# endif
# ifndef CURL_DISABLE_SMTP
# define CURL_DISABLE_SMTP
# endif
-# ifndef CURL_DISABLE_GOPHER
-# define CURL_DISABLE_GOPHER
+# ifndef CURL_DISABLE_TELNET
+# define CURL_DISABLE_TELNET
# endif
-# ifndef CURL_DISABLE_SMB
-# define CURL_DISABLE_SMB
+# ifndef CURL_DISABLE_TFTP
+# define CURL_DISABLE_TFTP
# endif
#endif
@@ -471,6 +477,15 @@
#endif
#endif
+#ifndef SSIZE_T_MAX
+/* some limits.h headers have this defined, some don't */
+#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
+#define SSIZE_T_MAX 9223372036854775807
+#else
+#define SSIZE_T_MAX 2147483647
+#endif
+#endif
+
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/
@@ -659,24 +674,16 @@ int netware_init(void);
#endif
/* Single point where USE_NTLM definition might be defined */
-#ifndef CURL_DISABLE_CRYPTO_AUTH
-#if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
- defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
- defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
- (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
-
-#define USE_CURL_NTLM_CORE
-
-# if defined(USE_MBEDTLS)
-/* Get definition of MBEDTLS_MD4_C */
-# include <mbedtls/md4.h>
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(CURL_DISABLE_NTLM)
+# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
+ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
+ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
+ (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
+# define USE_CURL_NTLM_CORE
+# endif
+# if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
+# define USE_NTLM
# endif
-
-#endif
-
-#if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
-#define USE_NTLM
-#endif
#endif
#ifdef CURL_WANTS_CA_BUNDLE_ENV
@@ -834,4 +841,20 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define ENABLE_QUIC
#endif
+#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
+# if defined(__MINGW32__) && !defined(LUP_SECURE)
+ typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */
+# endif
+# if !defined(UNIX_PATH_MAX)
+ /* Replicating logic present in afunix.h
+ (distributed with newer Windows 10 SDK versions only) */
+# define UNIX_PATH_MAX 108
+ /* !checksrc! disable TYPEDEFSTRUCT 1 */
+ typedef struct sockaddr_un {
+ ADDRESS_FAMILY sun_family;
+ char sun_path[UNIX_PATH_MAX];
+ } SOCKADDR_UN, *PSOCKADDR_UN;
+# endif
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index 22d0a063e..38018d23c 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -323,26 +323,6 @@ struct timeval {
#include "curl_ctype.h"
-/*
- * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
- */
-
-#ifndef HAVE_SIG_ATOMIC_T
-typedef int sig_atomic_t;
-#define HAVE_SIG_ATOMIC_T
-#endif
-
-
-/*
- * Convenience SIG_ATOMIC_T definition
- */
-
-#ifdef HAVE_SIG_ATOMIC_T_VOLATILE
-#define SIG_ATOMIC_T static sig_atomic_t
-#else
-#define SIG_ATOMIC_T static volatile sig_atomic_t
-#endif
-
/*
* Macro used to include code only in debug builds.
diff --git a/Utilities/cmcurl/lib/dict.c b/Utilities/cmcurl/lib/dict.c
index 625b05777..5d53b8f1f 100644
--- a/Utilities/cmcurl/lib/dict.c
+++ b/Utilities/cmcurl/lib/dict.c
@@ -216,7 +216,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
if(!word || (*word == (char)0)) {
- infof(data, "lookup word is missing\n");
+ infof(data, "lookup word is missing");
word = (char *)"default";
}
if(!database || (*database == (char)0)) {
@@ -267,7 +267,7 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
if(!word || (*word == (char)0)) {
- infof(data, "lookup word is missing\n");
+ infof(data, "lookup word is missing");
word = (char *)"default";
}
if(!database || (*database == (char)0)) {
diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c
index 36f8cd58d..de0c902b8 100644
--- a/Utilities/cmcurl/lib/doh.c
+++ b/Utilities/cmcurl/lib/doh.c
@@ -186,19 +186,19 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
return realsize;
}
-/* called from multi.c when this DOH transfer is complete */
+/* called from multi.c when this DoH transfer is complete */
static int doh_done(struct Curl_easy *doh, CURLcode result)
{
struct Curl_easy *data = doh->set.dohfor;
struct dohdata *dohp = data->req.doh;
- /* so one of the DOH request done for the 'data' transfer is now complete! */
+ /* so one of the DoH request done for the 'data' transfer is now complete! */
dohp->pending--;
- infof(data, "a DOH request is completed, %u to go\n", dohp->pending);
+ infof(data, "a DoH request is completed, %u to go", dohp->pending);
if(result)
- infof(data, "DOH request %s\n", curl_easy_strerror(result));
+ infof(data, "DoH request %s", curl_easy_strerror(result));
if(!dohp->pending) {
- /* DOH completed */
+ /* DoH completed */
curl_slist_free_all(dohp->headers);
dohp->headers = NULL;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
@@ -228,7 +228,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
&p->dohlen);
if(d) {
- failf(data, "Failed to encode DOH packet [%d]", d);
+ failf(data, "Failed to encode DoH packet [%d]", d);
return CURLE_OUT_OF_MEMORY;
}
@@ -302,7 +302,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* Inherit *some* SSL options from the user's transfer. This is a
best-guess as to which options are needed for compatibility. #3661
- Note DOH does not inherit the user's proxy server so proxy SSL settings
+ Note DoH does not inherit the user's proxy server so proxy SSL settings
have no effect and are not inherited. If that changes then two new
options should be added to check doh proxy insecure separately,
CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER.
@@ -359,17 +359,17 @@ static CURLcode dohprobe(struct Curl_easy *data,
(data->set.ssl.auto_client_cert ?
CURLSSLOPT_AUTO_CLIENT_CERT : 0);
- curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
+ (void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
}
doh->set.fmultidone = doh_done;
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
- /* DOH private_data must be null because the user must have a way to
- distinguish their transfer's handle from DOH handles in user
+ /* DoH private_data must be null because the user must have a way to
+ distinguish their transfer's handle from DoH handles in user
callbacks (ie SSL CTX callback). */
- DEBUGASSERT(!data->set.private_data);
+ DEBUGASSERT(!doh->set.private_data);
if(curl_multi_add_handle(multi, doh))
goto error;
@@ -386,7 +386,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
/*
- * Curl_doh() resolves a name using DOH. It resolves a name and returns a
+ * Curl_doh() resolves a name using DoH. It resolves a name and returns a
* 'Curl_addrinfo *' with the address information.
*/
@@ -420,7 +420,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
if(!dohp->headers)
goto error;
- /* create IPv4 DOH request */
+ /* create IPv4 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
data->multi, dohp->headers);
@@ -429,7 +429,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
dohp->pending++;
if(Curl_ipv6works(data)) {
- /* create IPv6 DOH request */
+ /* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
data->multi, dohp->headers);
@@ -764,11 +764,11 @@ static void showdoh(struct Curl_easy *data,
const struct dohentry *d)
{
int i;
- infof(data, "TTL: %u seconds\n", d->ttl);
+ infof(data, "TTL: %u seconds", d->ttl);
for(i = 0; i < d->numaddr; i++) {
const struct dohaddr *a = &d->addr[i];
if(a->type == DNS_TYPE_A) {
- infof(data, "DOH A: %u.%u.%u.%u\n",
+ infof(data, "DoH A: %u.%u.%u.%u",
a->ip.v4[0], a->ip.v4[1],
a->ip.v4[2], a->ip.v4[3]);
}
@@ -777,7 +777,7 @@ static void showdoh(struct Curl_easy *data,
char buffer[128];
char *ptr;
size_t len;
- msnprintf(buffer, 128, "DOH AAAA: ");
+ msnprintf(buffer, 128, "DoH AAAA: ");
ptr = &buffer[10];
len = 118;
for(j = 0; j < 16; j += 2) {
@@ -788,11 +788,11 @@ static void showdoh(struct Curl_easy *data,
len -= l;
ptr += l;
}
- infof(data, "%s\n", buffer);
+ infof(data, "%s", buffer);
}
}
for(i = 0; i < d->numcname; i++) {
- infof(data, "CNAME: %s\n", Curl_dyn_ptr(&d->cname[i]));
+ infof(data, "CNAME: %s", Curl_dyn_ptr(&d->cname[i]));
}
}
#else
@@ -803,7 +803,7 @@ static void showdoh(struct Curl_easy *data,
* doh2ai()
*
* This function returns a pointer to the first element of a newly allocated
- * Curl_addrinfo struct linked list filled with the data from a set of DOH
+ * Curl_addrinfo struct linked list filled with the data from a set of DoH
* lookups. Curl_addrinfo is meant to work like the addrinfo struct does for
* a IPv6 stack, but usable also for IPv4, all hosts and environments.
*
@@ -931,7 +931,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
- failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
+ failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
@@ -941,7 +941,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
};
struct dohentry de;
int slot;
- /* remove DOH handles from multi handle and close them */
+ /* remove DoH handles from multi handle and close them */
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
Curl_close(&dohp->probe[slot].easy);
@@ -958,7 +958,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
&de);
Curl_dyn_free(&p->serverdoh);
if(rc[slot]) {
- infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
+ infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
type2name(p->dnstype), dohp->host);
}
} /* next slot */
@@ -969,7 +969,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry *dns;
struct Curl_addrinfo *ai;
- infof(data, "DOH Host name: %s\n", dohp->host);
+ infof(data, "DoH Host name: %s", dohp->host);
showdoh(data, &de);
ai = doh2ai(&de, dohp->host, dohp->port);
@@ -1007,7 +1007,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
} /* !dohp->pending */
- /* else wait for pending DOH transactions to complete */
+ /* else wait for pending DoH transactions to complete */
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/doh.h b/Utilities/cmcurl/lib/doh.h
index b3584d1b2..70e96e012 100644
--- a/Utilities/cmcurl/lib/doh.h
+++ b/Utilities/cmcurl/lib/doh.h
@@ -101,7 +101,7 @@ void de_init(struct dohentry *d);
void de_cleanup(struct dohentry *d);
#endif
-#else /* if DOH is disabled */
+#else /* if DoH is disabled */
#define Curl_doh(a,b,c,d) NULL
#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#endif
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 530b7c73f..2aca93845 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -117,7 +117,7 @@ curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
#if defined(WIN32) && defined(UNICODE)
-curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
+curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
#endif
#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
@@ -417,13 +417,13 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
ev->list = nxt;
free(m);
m = nxt;
- infof(easy, "socket cb: socket %d REMOVED\n", s);
+ infof(easy, "socket cb: socket %d REMOVED", s);
}
else {
/* The socket 's' is already being monitored, update the activity
mask. Convert from libcurl bitmask to the poll one. */
m->socket.events = socketcb2poll(what);
- infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
+ infof(easy, "socket cb: socket %d UPDATED as %s%s", s,
(what&CURL_POLL_IN)?"IN":"",
(what&CURL_POLL_OUT)?"OUT":"");
}
@@ -447,7 +447,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
m->socket.events = socketcb2poll(what);
m->socket.revents = 0;
ev->list = m;
- infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
+ infof(easy, "socket cb: socket %d ADDED as %s%s", s,
(what&CURL_POLL_IN)?"IN":"",
(what&CURL_POLL_OUT)?"OUT":"");
}
@@ -532,7 +532,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
if(fds[i].revents) {
/* socket activity, tell libcurl */
int act = poll2cselect(fds[i].revents); /* convert */
- infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n",
+ infof(multi->easyp, "call curl_multi_socket_action(socket %d)",
fds[i].fd);
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
&ev->running_handles);
@@ -1027,7 +1027,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) {
/* Not changing any pause state, return */
- DEBUGF(infof(data, "pause: no change, early return\n"));
+ DEBUGF(infof(data, "pause: no change, early return"));
return CURLE_OK;
}
@@ -1213,9 +1213,16 @@ static int conn_upkeep(struct Curl_easy *data,
/* Param is unused. */
(void)param;
- if(conn->handler->connection_check)
+ if(conn->handler->connection_check) {
+ /* briefly attach the connection to this transfer for the purpose of
+ checking it */
+ Curl_attach_connnection(data, conn);
+
/* Do a protocol-specific keepalive check on the connection. */
conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
+ /* detach the connection again */
+ Curl_detach_connnection(data);
+ }
return 0; /* continue iteration */
}
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 769f06a70..ac7a0009c 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -865,8 +865,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
if(post->flags & CURL_HTTPPOST_LARGE)
clen = post->contentlen;
- if(!clen)
- clen = -1;
if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
if(!strcmp(file->contents, "-")) {
@@ -888,13 +886,21 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
else if(post->flags & HTTPPOST_BUFFER)
result = curl_mime_data(part, post->buffer,
post->bufferlength? post->bufferlength: -1);
- else if(post->flags & HTTPPOST_CALLBACK)
+ else if(post->flags & HTTPPOST_CALLBACK) {
/* the contents should be read with the callback and the size is set
with the contentslength */
+ if(!clen)
+ clen = -1;
result = curl_mime_data_cb(part, clen,
fread_func, NULL, NULL, post->userp);
+ }
else {
- result = curl_mime_data(part, post->contents, (ssize_t) clen);
+ size_t uclen;
+ if(!clen)
+ uclen = CURL_ZERO_TERMINATED;
+ else
+ uclen = (size_t)clen;
+ result = curl_mime_data(part, post->contents, uclen);
#ifdef CURL_DOES_CONVERSIONS
/* Convert textual contents now. */
if(!result && data && part->datasize)
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 425b0afec..cad584f24 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -289,7 +289,7 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
failf(data, "Error accept()ing server connect");
return CURLE_FTP_PORT_FAILED;
}
- infof(data, "Connection accepted from server\n");
+ infof(data, "Connection accepted from server");
/* when this happens within the DO state it is important that we mark us as
not needing DO_MORE anymore */
conn->bits.do_more = FALSE;
@@ -380,7 +380,7 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
*received = FALSE;
timeout_ms = ftp_timeleft_accept(data);
- infof(data, "Checking for server connect\n");
+ infof(data, "Checking for server connect");
if(timeout_ms < 0) {
/* if a timeout was already reached, bail out */
failf(data, "Accept timeout occurred while waiting server connect");
@@ -390,7 +390,7 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
/* First check whether there is a cached response from server */
if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
/* Data connection could not be established, let's return */
- infof(data, "There is negative response in cache while serv connect\n");
+ infof(data, "There is negative response in cache while serv connect");
(void)Curl_GetFTPResponse(data, &nread, &ftpcode);
return CURLE_FTP_ACCEPT_FAILED;
}
@@ -408,11 +408,11 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
default:
if(result & CURL_CSELECT_IN2) {
- infof(data, "Ready to accept data connection from server\n");
+ infof(data, "Ready to accept data connection from server");
*received = TRUE;
}
else if(result & CURL_CSELECT_IN) {
- infof(data, "Ctrl conn has data while waiting for data conn\n");
+ infof(data, "Ctrl conn has data while waiting for data conn");
(void)Curl_GetFTPResponse(data, &nread, &ftpcode);
if(ftpcode/100 > 3)
@@ -444,7 +444,7 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
- infof(data, "Doing the SSL/TLS handshake on the data stream\n");
+ infof(data, "Doing the SSL/TLS handshake on the data stream");
result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
if(result)
return result;
@@ -487,7 +487,7 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
CURLcode result = CURLE_OK;
*connected = FALSE;
- infof(data, "Preparing for accepting server on data port\n");
+ infof(data, "Preparing for accepting server on data port");
/* Save the time we start accepting server connect */
Curl_pgrsTime(data, TIMER_STARTACCEPT);
@@ -592,7 +592,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
* This response code can come at any point so having it treated
* generically is a good idea.
*/
- infof(data, "We got a 421 - timeout!\n");
+ infof(data, "We got a 421 - timeout!");
state(data, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -768,7 +768,7 @@ static void _state(struct Curl_easy *data,
(void) lineno;
#else
if(ftpc->state != newstate)
- infof(data, "FTP %p (line %d) state change from %s to %s\n",
+ infof(data, "FTP %p (line %d) state change from %s to %s",
(void *)ftpc, lineno, ftp_state_names[ftpc->state],
ftp_state_names[newstate]);
#endif
@@ -1139,7 +1139,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
/* The requested bind address is not local. Use the address used for
* the control connection instead and restart the port loop
*/
- infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
+ infof(data, "bind(port=%hu) on non-local address failed: %s", port,
Curl_strerror(error, buffer, sizeof(buffer)));
sslen = sizeof(ss);
@@ -1341,7 +1341,7 @@ static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
if(!result) {
ftpc->count1 = modeoff;
state(data, FTP_PASV);
- infof(data, "Connect data stream passively\n");
+ infof(data, "Connect data stream passively");
}
return result;
}
@@ -1648,7 +1648,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
data->state.infilesize -= data->state.resume_from;
if(data->state.infilesize <= 0) {
- infof(data, "File already completely uploaded\n");
+ infof(data, "File already completely uploaded");
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
@@ -1802,7 +1802,7 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
return CURLE_WEIRD_SERVER_REPLY;
}
- infof(data, "Failed EPSV attempt. Disabling EPSV\n");
+ infof(data, "Failed EPSV attempt. Disabling EPSV");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
data->state.errorbuf = FALSE; /* allow error message to get
@@ -1921,7 +1921,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
if(data->set.ftp_skip_ip) {
/* told to ignore the remotely given IP but instead use the host we used
for the control connection */
- infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead\n",
+ infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead",
ip[0], ip[1], ip[2], ip[3],
conn->host.name);
ftpc->newhost = strdup(control_address(conn));
@@ -2044,7 +2044,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data,
/* the command failed */
if(EPRT == fcmd) {
- infof(data, "disabling EPRT usage\n");
+ infof(data, "disabling EPRT usage");
conn->bits.ftp_use_eprt = FALSE;
}
fcmd++;
@@ -2058,7 +2058,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data,
result = ftp_state_use_port(data, fcmd);
}
else {
- infof(data, "Connect data stream actively\n");
+ infof(data, "Connect data stream actively");
state(data, FTP_STOP); /* end of DO phase */
result = ftp_dophase_done(data, FALSE);
}
@@ -2128,7 +2128,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
}
break;
default:
- infof(data, "unsupported MDTM reply format\n");
+ infof(data, "unsupported MDTM reply format");
break;
case 550: /* "No such file or directory" */
failf(data, "Given file does not exist");
@@ -2142,7 +2142,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
case CURL_TIMECOND_IFMODSINCE:
default:
if(data->info.filetime <= data->set.timevalue) {
- infof(data, "The requested document is not new enough\n");
+ infof(data, "The requested document is not new enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
state(data, FTP_STOP);
@@ -2151,7 +2151,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
break;
case CURL_TIMECOND_IFUNMODSINCE:
if(data->info.filetime > data->set.timevalue) {
- infof(data, "The requested document is not old enough\n");
+ infof(data, "The requested document is not old enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
state(data, FTP_STOP);
@@ -2161,7 +2161,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
} /* switch */
}
else {
- infof(data, "Skipping time comparison\n");
+ infof(data, "Skipping time comparison");
}
}
@@ -2186,7 +2186,7 @@ static CURLcode ftp_state_type_resp(struct Curl_easy *data,
return CURLE_FTP_COULDNT_SET_TYPE;
}
if(ftpcode != 200)
- infof(data, "Got a %03d response code instead of the assumed 200\n",
+ infof(data, "Got a %03d response code instead of the assumed 200",
ftpcode);
if(instate == FTP_TYPE)
@@ -2219,7 +2219,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
/* We always (attempt to) get the size of downloads, so it is done before
this even when not doing resumes. */
if(filesize == -1) {
- infof(data, "ftp server doesn't support SIZE\n");
+ infof(data, "ftp server doesn't support SIZE");
/* We couldn't get the size and therefore we can't know if there really
is a part of the file left to get, although the server will just
close the connection when we start the connection so it won't cause
@@ -2256,7 +2256,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
if(ftp->downloadsize == 0) {
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- infof(data, "File already completely downloaded\n");
+ infof(data, "File already completely downloaded");
/* Set ->transfer so that we won't get any error in ftp_done()
* because we didn't transfer the any file */
@@ -2267,7 +2267,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
/* Set resume file transfer offset */
infof(data, "Instructs server to resume from offset %"
- CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
+ CURL_FORMAT_CURL_OFF_T, data->state.resume_from);
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
data->state.resume_from);
@@ -2413,7 +2413,7 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
- infof(data, "Data conn was not available immediately\n");
+ infof(data, "Data conn was not available immediately");
ftpc->wait_data_conn = TRUE;
}
@@ -2506,11 +2506,11 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
else if((instate != FTP_LIST) && (data->state.prefer_ascii))
size = -1; /* kludge for servers that understate ASCII mode file size */
- infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
+ infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T,
data->req.maxdownload);
if(instate != FTP_LIST)
- infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n",
+ infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T,
size);
/* FTP download: */
@@ -2526,7 +2526,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
- infof(data, "Data conn was not available immediately\n");
+ infof(data, "Data conn was not available immediately");
state(data, FTP_STOP);
ftpc->wait_data_conn = TRUE;
}
@@ -2681,9 +2681,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* we have now received a full FTP server response */
switch(ftpc->state) {
case FTP_WAIT220:
- if(ftpcode == 230)
- /* 230 User logged in - already! */
- return ftp_state_user_resp(data, ftpcode, ftpc->state);
+ if(ftpcode == 230) {
+ /* 230 User logged in - already! Take as 220 if TLS required. */
+ if(data->set.use_ssl <= CURLUSESSL_TRY ||
+ conn->bits.ftp_use_control_ssl)
+ return ftp_state_user_resp(data, ftpcode, ftpc->state);
+ }
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
@@ -2702,9 +2705,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
if(Curl_sec_login(data, conn))
- infof(data, "Logging in with password in cleartext!\n");
+ infof(data, "Logging in with password in cleartext!");
else
- infof(data, "Authentication successful\n");
+ infof(data, "Authentication successful");
}
#endif
@@ -2740,6 +2743,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_AUTH:
/* we have gotten the response to a previous AUTH command */
+ if(pp->cache_size)
+ return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
+
/* RFC2228 (page 5) says:
*
* If the server is willing to accept the named security mechanism,
@@ -2895,7 +2901,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
Curl_safefree(ftpc->entrypath);
ftpc->entrypath = dir; /* remember this */
- infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ infof(data, "Entry path is '%s'", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
state(data, FTP_SYST);
@@ -2904,18 +2910,18 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
Curl_safefree(ftpc->entrypath);
ftpc->entrypath = dir; /* remember this */
- infof(data, "Entry path is '%s'\n", ftpc->entrypath);
+ infof(data, "Entry path is '%s'", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
}
else {
/* couldn't get the path */
free(dir);
- infof(data, "Failed to figure out path\n");
+ infof(data, "Failed to figure out path");
}
}
state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ DEBUGF(infof(data, "protocol connect phase DONE"));
break;
case FTP_SYST:
@@ -2962,7 +2968,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ DEBUGF(infof(data, "protocol connect phase DONE"));
break;
case FTP_NAMEFMT:
@@ -2973,7 +2979,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
state(data, FTP_STOP); /* we are done with the CONNECT phase! */
- DEBUGF(infof(data, "protocol connect phase DONE\n"));
+ DEBUGF(infof(data, "protocol connect phase DONE"));
break;
case FTP_QUOTE:
@@ -3272,7 +3278,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
}
if(ftpc->prevpath)
- infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
+ infof(data, "Remembering we are in dir \"%s\"", ftpc->prevpath);
}
/* free the dir tree and file parts */
@@ -3338,7 +3344,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
if(ftpc->dont_check && data->req.maxdownload > 0) {
/* we have just sent ABOR and there is no reliable way to check if it was
* successful or not; we have to close the connection now */
- infof(data, "partial download completed, closing connection\n");
+ infof(data, "partial download completed, closing connection");
connclose(conn, "Partial download with no ability to check");
return result;
}
@@ -3529,7 +3535,7 @@ ftp_pasv_verbose(struct Curl_easy *data,
{
char buf[256];
Curl_printable_address(ai, buf, sizeof(buf));
- infof(data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
+ infof(data, "Connecting to %s (%s) port %d", newhost, buf, port);
}
#endif
@@ -3569,7 +3575,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
/* Ready to do more? */
if(connected) {
- DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
+ DEBUGF(infof(data, "DO-MORE connected phase starts"));
}
else {
if(result && (ftpc->count1 == 0)) {
@@ -3644,8 +3650,13 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
return result;
result = ftp_multi_statemach(data, &complete);
- /* ftpc->wait_data_conn is always false here */
- *completep = (int)complete;
+ if(ftpc->wait_data_conn)
+ /* if we reach the end of the FTP state machine here, *complete will be
+ TRUE but so is ftpc->wait_data_conn, which says we need to wait for
+ the data connection and therefore we're not actually complete */
+ *completep = 0;
+ else
+ *completep = (int)complete;
}
else {
/* download */
@@ -3692,7 +3703,7 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
if(!ftpc->wait_data_conn) {
/* no waiting for the data connection so this is now complete */
*completep = 1;
- DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
+ DEBUGF(infof(data, "DO-MORE phase ends with %d", (int)result));
}
return result;
@@ -3717,7 +3728,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
/* requested no body means no transfer... */
@@ -3737,10 +3748,10 @@ CURLcode ftp_perform(struct Curl_easy *data,
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
- infof(data, "ftp_perform ends with SECONDARY: %d\n", *connected);
+ infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete1\n"));
+ DEBUGF(infof(data, "DO phase is complete1"));
}
return result;
@@ -3835,7 +3846,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
/* let the writefunc callback know the transfer */
data->set.out = data;
- infof(data, "Wildcard - Parsing started\n");
+ infof(data, "Wildcard - Parsing started");
return CURLE_OK;
fail:
@@ -3902,7 +3913,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
free(ftp->pathalloc);
ftp->pathalloc = ftp->path = tmp_path;
- infof(data, "Wildcard - START of \"%s\"\n", finfo->filename);
+ infof(data, "Wildcard - START of \"%s\"", finfo->filename);
if(data->set.chunk_bgn) {
long userresponse;
Curl_set_in_callback(data, true);
@@ -3911,7 +3922,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
Curl_set_in_callback(data, false);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
- infof(data, "Wildcard - \"%s\" skipped by user\n",
+ infof(data, "Wildcard - \"%s\" skipped by user",
finfo->filename);
wildcard->state = CURLWC_SKIP;
continue;
@@ -4234,7 +4245,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
n -= ftpc->file?strlen(ftpc->file):0;
if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
- infof(data, "Request has same path as previous transfer\n");
+ infof(data, "Request has same path as previous transfer");
ftpc->cwddone = TRUE;
}
}
@@ -4280,11 +4291,11 @@ static CURLcode ftp_doing(struct Curl_easy *data,
CURLcode result = ftp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
result = ftp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(data, "DO phase is complete2\n"));
+ DEBUGF(infof(data, "DO phase is complete2"));
}
return result;
}
diff --git a/Utilities/cmcurl/lib/hostasyn.c b/Utilities/cmcurl/lib/hostasyn.c
index b25de1d41..f7d99ce9a 100644
--- a/Utilities/cmcurl/lib/hostasyn.c
+++ b/Utilities/cmcurl/lib/hostasyn.c
@@ -50,7 +50,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "curl_memory.h"
/* The last #include file should be: */
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 49dbab347..cf267a765 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -36,7 +36,7 @@
#include "hostcheck.h"
#include "strcase.h"
-#include "inet_pton.h"
+#include "hostip.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -67,10 +67,6 @@ static int hostmatch(char *hostname, char *pattern)
const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
int wildcard_enabled;
size_t prefixlen, suffixlen;
- struct in_addr ignored;
-#ifdef ENABLE_IPV6
- struct sockaddr_in6 si6;
-#endif
/* normalize pattern and hostname by stripping off trailing dots */
size_t len = strlen(hostname);
@@ -86,12 +82,8 @@ static int hostmatch(char *hostname, char *pattern)
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
/* detect IP address as hostname and fail the match if so */
- if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
- return CURL_HOST_NOMATCH;
-#ifdef ENABLE_IPV6
- if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
+ if(Curl_host_is_ipnum(hostname))
return CURL_HOST_NOMATCH;
-#endif
/* We require at least 2 dots in pattern to avoid too wide wildcard
match. */
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index e0e3cfc2c..117caa295 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -56,13 +56,13 @@
#include "hash.h"
#include "rand.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "inet_ntop.h"
#include "inet_pton.h"
#include "multiif.h"
#include "doh.h"
#include "warnless.h"
+#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -289,7 +289,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
user.cache_timeout = data->set.dns_cache_timeout;
if(hostcache_timestamp_remove(&user, dns)) {
- infof(data, "Hostname in DNS cache was stale, zapped\n");
+ infof(data, "Hostname in DNS cache was stale, zapped");
dns = NULL; /* the memory deallocation is being handled by the hash */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
}
@@ -460,6 +460,127 @@ Curl_cache_addr(struct Curl_easy *data,
return dns;
}
+#ifdef ENABLE_IPV6
+/* return a static IPv6 resolve for 'localhost' */
+static struct Curl_addrinfo *get_localhost6(int port)
+{
+ struct Curl_addrinfo *ca;
+ const size_t ss_size = sizeof(struct sockaddr_in6);
+ const size_t hostlen = strlen("localhost");
+ struct sockaddr_in6 sa6;
+ unsigned char ipv6[16];
+ unsigned short port16 = (unsigned short)(port & 0xffff);
+ ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ if(!ca)
+ return NULL;
+
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_port = htons(port16);
+ sa6.sin6_flowinfo = 0;
+ sa6.sin6_scope_id = 0;
+ if(Curl_inet_pton(AF_INET6, "::1", ipv6) < 1)
+ return NULL;
+ memcpy(&sa6.sin6_addr, ipv6, sizeof(ipv6));
+
+ ca->ai_flags = 0;
+ ca->ai_family = AF_INET6;
+ ca->ai_socktype = SOCK_STREAM;
+ ca->ai_protocol = IPPROTO_TCP;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_next = NULL;
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
+ memcpy(ca->ai_addr, &sa6, ss_size);
+ ca->ai_canonname = (char *)ca->ai_addr + ss_size;
+ strcpy(ca->ai_canonname, "localhost");
+ return ca;
+}
+#else
+#define get_localhost6(x) NULL
+#endif
+
+/* return a static IPv4 resolve for 'localhost' */
+static struct Curl_addrinfo *get_localhost(int port)
+{
+ struct Curl_addrinfo *ca;
+ const size_t ss_size = sizeof(struct sockaddr_in);
+ const size_t hostlen = strlen("localhost");
+ struct sockaddr_in sa;
+ unsigned int ipv4;
+ unsigned short port16 = (unsigned short)(port & 0xffff);
+ ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ if(!ca)
+ return NULL;
+
+ /* memset to clear the sa.sin_zero field */
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(port16);
+ if(Curl_inet_pton(AF_INET, "127.0.0.1", (char *)&ipv4) < 1)
+ return NULL;
+ memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
+
+ ca->ai_flags = 0;
+ ca->ai_family = AF_INET;
+ ca->ai_socktype = SOCK_STREAM;
+ ca->ai_protocol = IPPROTO_TCP;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
+ memcpy(ca->ai_addr, &sa, ss_size);
+ ca->ai_canonname = (char *)ca->ai_addr + ss_size;
+ strcpy(ca->ai_canonname, "localhost");
+ ca->ai_next = get_localhost6(port);
+ return ca;
+}
+
+#ifdef ENABLE_IPV6
+/*
+ * Curl_ipv6works() returns TRUE if IPv6 seems to work.
+ */
+bool Curl_ipv6works(struct Curl_easy *data)
+{
+ if(data) {
+ /* the nature of most system is that IPv6 status doesn't come and go
+ during a program's lifetime so we only probe the first time and then we
+ have the info kept for fast re-use */
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->multi);
+ return data->multi->ipv6_works;
+ }
+ else {
+ int ipv6_works = -1;
+ /* probe to see if we have a working IPv6 stack */
+ curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if(s == CURL_SOCKET_BAD)
+ /* an IPv6 address was requested but we can't get/use one */
+ ipv6_works = 0;
+ else {
+ ipv6_works = 1;
+ sclose(s);
+ }
+ return (ipv6_works>0)?TRUE:FALSE;
+ }
+}
+#endif /* ENABLE_IPV6 */
+
+/*
+ * Curl_host_is_ipnum() returns TRUE if the given string is a numerical IPv4
+ * (or IPv6 if supported) address.
+ */
+bool Curl_host_is_ipnum(const char *hostname)
+{
+ struct in_addr in;
+#ifdef ENABLE_IPV6
+ struct in6_addr in6;
+#endif
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, hostname, &in6) > 0
+#endif
+ )
+ return TRUE;
+ return FALSE;
+}
+
/*
* Curl_resolv() is the main name resolve function within libcurl. It resolves
* a name and returns a pointer to the entry in the 'entry' argument (if one
@@ -487,7 +608,6 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
struct connectdata *conn = data->conn;
-
*entry = NULL;
conn->bits.doh = FALSE; /* default is not */
@@ -497,7 +617,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
dns = fetch_addr(data, hostname, port);
if(dns) {
- infof(data, "Hostname %s was found in DNS cache\n", hostname);
+ infof(data, "Hostname %s was found in DNS cache", hostname);
dns->inuse++; /* we use it! */
rc = CURLRESOLV_RESOLVED;
}
@@ -534,16 +654,20 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
}
#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
- /*
- * The automagic conversion from IPv4 literals to IPv6 literals only works
- * if the SCDynamicStoreCopyProxies system function gets called first. As
- * Curl currently doesn't support system-wide HTTP proxies, we therefore
- * don't use any value this function might return.
- *
- * This function is only available on a macOS and is not needed for
- * IPv4-only builds, hence the conditions above.
- */
- SCDynamicStoreCopyProxies(NULL);
+ {
+ /*
+ * The automagic conversion from IPv4 literals to IPv6 literals only
+ * works if the SCDynamicStoreCopyProxies system function gets called
+ * first. As Curl currently doesn't support system-wide HTTP proxies, we
+ * therefore don't use any value this function might return.
+ *
+ * This function is only available on a macOS and is not needed for
+ * IPv4-only builds, hence the conditions above.
+ */
+ CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
+ if(dict)
+ CFRelease(dict);
+ }
#endif
#ifndef USE_RESOLVE_ON_IPS
@@ -579,15 +703,18 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
#endif /* !USE_RESOLVE_ON_IPS */
if(!addr) {
- /* Check what IP specifics the app has requested and if we can provide
- * it. If not, bail out. */
- if(!Curl_ipvalid(data, conn))
+ if(conn->ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data))
return CURLRESOLV_ERROR;
- if(allowDOH && data->set.doh && !ipnum) {
+ if(strcasecompare(hostname, "localhost"))
+ addr = get_localhost(port);
+ else if(allowDOH && data->set.doh && !ipnum)
addr = Curl_doh(data, hostname, port, &respwait);
- }
else {
+ /* Check what IP specifics the app has requested and if we can provide
+ * it. If not, bail out. */
+ if(!Curl_ipvalid(data, conn))
+ return CURLRESOLV_ERROR;
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to
the resolve call */
@@ -757,7 +884,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
#else
#ifndef CURLRES_ASYNCH
if(timeoutms)
- infof(data, "timeout on name lookup is not supported\n");
+ infof(data, "timeout on name lookup is not supported");
#else
(void)timeoutms; /* timeoutms not used with an async resolver */
#endif
@@ -895,7 +1022,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
size_t entry_len;
if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n",
+ infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'",
hostp->data);
continue;
}
@@ -984,7 +1111,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
#ifndef ENABLE_IPV6
if(strchr(address, ':')) {
- infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n",
+ infof(data, "Ignoring resolve address '%s', missing IPv6 support.",
address);
continue;
}
@@ -992,7 +1119,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
ai = Curl_str2addr(address, port);
if(!ai) {
- infof(data, "Resolve address '%s' found illegal!\n", address);
+ infof(data, "Resolve address '%s' found illegal!", address);
goto err;
}
@@ -1011,10 +1138,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
error = false;
err:
if(error) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
+ failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!",
hostp->data);
Curl_freeaddrinfo(head);
- continue;
+ return CURLE_SETOPT_OPTION_SYNTAX;
}
/* Create an entry id, based upon the hostname and port */
@@ -1028,7 +1155,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
if(dns) {
- infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
+ infof(data, "RESOLVE %s:%d is - old addresses discarded!",
hostname, port);
/* delete old entry, there are two reasons for this
1. old entry may have different addresses.
@@ -1061,12 +1188,12 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
- infof(data, "Added %s:%d:%s to DNS cache%s\n",
+ infof(data, "Added %s:%d:%s to DNS cache%s",
hostname, port, addresses, permanent ? "" : " (non-permanent)");
/* Wildcard hostname */
if(hostname[0] == '*' && hostname[1] == '\0') {
- infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
+ infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks",
hostname, port);
data->state.wildcard_resolve = true;
}
@@ -1094,7 +1221,7 @@ int Curl_resolv_getsock(struct Curl_easy *data,
{
#ifdef CURLRES_ASYNCH
if(data->conn->bits.doh)
- /* nothing to wait for during DOH resolve, those handles have their own
+ /* nothing to wait for during DoH resolve, those handles have their own
sockets */
return GETSOCK_BLANK;
return Curl_resolver_getsock(data, socks);
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index d178976aa..67a688aeb 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -71,6 +71,8 @@ struct Curl_dns_entry {
long inuse;
};
+bool Curl_host_is_ipnum(const char *hostname);
+
/*
* Curl_resolv() returns an entry with the info for the specified host
* and port.
@@ -95,7 +97,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry,
timediff_t timeoutms);
-#ifdef CURLRES_IPV6
+#ifdef ENABLE_IPV6
/*
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
*/
diff --git a/Utilities/cmcurl/lib/hostip4.c b/Utilities/cmcurl/lib/hostip4.c
index d0754af22..1fd791015 100644
--- a/Utilities/cmcurl/lib/hostip4.c
+++ b/Utilities/cmcurl/lib/hostip4.c
@@ -50,7 +50,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -104,7 +103,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai)
- infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
+ infof(data, "Curl_ipv4_resolve_r failed for %s", hostname);
return ai;
}
diff --git a/Utilities/cmcurl/lib/hostip6.c b/Utilities/cmcurl/lib/hostip6.c
index 9791d8646..c2d5f08e3 100644
--- a/Utilities/cmcurl/lib/hostip6.c
+++ b/Utilities/cmcurl/lib/hostip6.c
@@ -50,7 +50,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "inet_pton.h"
#include "connect.h"
@@ -60,34 +59,6 @@
#include "memdebug.h"
/*
- * Curl_ipv6works() returns TRUE if IPv6 seems to work.
- */
-bool Curl_ipv6works(struct Curl_easy *data)
-{
- if(data) {
- /* the nature of most system is that IPv6 status doesn't come and go
- during a program's lifetime so we only probe the first time and then we
- have the info kept for fast re-use */
- DEBUGASSERT(data);
- DEBUGASSERT(data->multi);
- return data->multi->ipv6_works;
- }
- else {
- int ipv6_works = -1;
- /* probe to see if we have a working IPv6 stack */
- curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
- if(s == CURL_SOCKET_BAD)
- /* an IPv6 address was requested but we can't get/use one */
- ipv6_works = 0;
- else {
- ipv6_works = 1;
- sclose(s);
- }
- return (ipv6_works>0)?TRUE:FALSE;
- }
-}
-
-/*
* Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
* been set and returns TRUE if they are OK.
*/
@@ -172,7 +143,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
if(error) {
- infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
+ infof(data, "getaddrinfo(3) failed for %s:%d", hostname, port);
return NULL;
}
diff --git a/Utilities/cmcurl/lib/hostsyn.c b/Utilities/cmcurl/lib/hostsyn.c
index 550b43a08..c00c2744c 100644
--- a/Utilities/cmcurl/lib/hostsyn.c
+++ b/Utilities/cmcurl/lib/hostsyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -50,7 +50,6 @@
#include "hostip.h"
#include "hash.h"
#include "share.h"
-#include "strerror.h"
#include "url.h"
#include "curl_memory.h"
/* The last #include file should be: */
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
index ef166f196..052dc1157 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -49,6 +49,7 @@
#define MAX_HSTS_HOSTLENSTR "256"
#define MAX_HSTS_DATELEN 64
#define MAX_HSTS_DATELENSTR "64"
+#define UNLIMITED "unlimited"
#ifdef DEBUGBUILD
/* to play well with debug builds, we can *set* a fixed time this will
@@ -138,6 +139,11 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
struct stsentry *sts;
time_t now = time(NULL);
+ if(Curl_host_is_ipnum(hostname))
+ /* "explicit IP address identification of all forms is excluded."
+ / RFC 6797 */
+ return CURLE_OK;
+
do {
while(*p && ISSPACE(*p))
p++;
@@ -278,13 +284,17 @@ static CURLcode hsts_push(struct Curl_easy *data,
e.namelen = strlen(sts->host);
e.includeSubDomains = sts->includeSubDomains;
- result = Curl_gmtime((time_t)sts->expires, &stamp);
- if(result)
- return result;
+ if(sts->expires != TIME_T_MAX) {
+ result = Curl_gmtime((time_t)sts->expires, &stamp);
+ if(result)
+ return result;
- msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
- stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
- stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ }
+ else
+ strcpy(e.expire, UNLIMITED);
sc = data->set.hsts_write(data, &e, i,
data->set.hsts_write_userp);
@@ -298,14 +308,18 @@ static CURLcode hsts_push(struct Curl_easy *data,
static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
{
struct tm stamp;
- CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
- if(result)
- return result;
-
- fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
- sts->includeSubDomains ? ".": "", sts->host,
- stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
- stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ if(sts->expires != TIME_T_MAX) {
+ CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp);
+ if(result)
+ return result;
+ fprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
+ sts->includeSubDomains ? ".": "", sts->host,
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ }
+ else
+ fprintf(fp, "%s%s \"%s\"\n",
+ sts->includeSubDomains ? ".": "", sts->host, UNLIMITED);
return CURLE_OK;
}
@@ -398,7 +412,8 @@ static CURLcode hsts_add(struct hsts *h, char *line)
"%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
host, date);
if(2 == rc) {
- time_t expires = Curl_getdate_capped(date);
+ time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) :
+ TIME_T_MAX;
CURLcode result;
char *p = host;
bool subdomain = FALSE;
@@ -451,7 +466,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
return result;
}
else if(sc == CURLSTS_FAIL)
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ return CURLE_ABORTED_BY_CALLBACK;
} while(sc == CURLSTS_OK);
}
return CURLE_OK;
@@ -521,7 +536,9 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
*/
CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
{
- return hsts_pull(data, h);
+ if(h)
+ return hsts_pull(data, h);
+ return CURLE_OK;
}
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
diff --git a/Utilities/cmcurl/lib/hsts.h b/Utilities/cmcurl/lib/hsts.h
index baa582864..653c05348 100644
--- a/Utilities/cmcurl/lib/hsts.h
+++ b/Utilities/cmcurl/lib/hsts.h
@@ -59,7 +59,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
struct hsts *h);
#else
#define Curl_hsts_cleanup(x)
-#define Curl_hsts_loadcb(x,y)
+#define Curl_hsts_loadcb(x,y) CURLE_OK
#define Curl_hsts_save(x,y,z)
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
#endif /* HEADER_CURL_HSTS_H */
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 628dd7370..648583c56 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -504,7 +504,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
- infof(data, "Rewind stream after send\n");
+ infof(data, "Rewind stream after send");
}
return CURLE_OK;
@@ -515,7 +515,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
return CURLE_OK;
infof(data, "NTLM send, close instead of sending %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
+ CURL_FORMAT_CURL_OFF_T " bytes",
(curl_off_t)(expectsend - bytessent));
}
#endif
@@ -532,7 +532,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
- infof(data, "Rewind stream after send\n");
+ infof(data, "Rewind stream after send");
}
return CURLE_OK;
@@ -543,7 +543,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
return CURLE_OK;
infof(data, "NEGOTIATE send, close instead of sending %"
- CURL_FORMAT_CURL_OFF_T " bytes\n",
+ CURL_FORMAT_CURL_OFF_T " bytes",
(curl_off_t)(expectsend - bytessent));
}
#endif
@@ -756,14 +756,14 @@ output_auth_headers(struct Curl_easy *data,
if(auth) {
#ifndef CURL_DISABLE_PROXY
- infof(data, "%s auth using %s with user '%s'\n",
+ infof(data, "%s auth using %s with user '%s'",
proxy ? "Proxy" : "Server", auth,
proxy ? (data->state.aptr.proxyuser ?
data->state.aptr.proxyuser : "") :
(data->state.aptr.user ?
data->state.aptr.user : ""));
#else
- infof(data, "Server auth using %s with user '%s'\n",
+ infof(data, "Server auth using %s with user '%s'",
auth, data->state.aptr.user ?
data->state.aptr.user : "");
#endif
@@ -850,7 +850,9 @@ Curl_http_output_auth(struct Curl_easy *data,
/* To prevent the user+password to get sent to other than the original
host due to a location-follow, we do some weirdo checks here */
if(!data->state.this_is_a_follow ||
+#ifndef CURL_DISABLE_NETRC
conn->bits.netrc ||
+#endif
!data->state.first_host ||
data->set.allow_auth_to_other_hosts ||
strcasecompare(data->state.first_host, conn->host.name)) {
@@ -995,14 +997,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
result = Curl_input_ntlm_wb(data, conn, proxy, auth);
if(result) {
- infof(data, "Authentication problem. Ignoring this.\n");
+ infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
}
}
#endif
}
else {
- infof(data, "Authentication problem. Ignoring this.\n");
+ infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
}
}
@@ -1013,7 +1015,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
if((authp->avail & CURLAUTH_DIGEST) != 0)
- infof(data, "Ignoring duplicate digest auth header.\n");
+ infof(data, "Ignoring duplicate digest auth header.");
else if(Curl_auth_is_digest_supported()) {
CURLcode result;
@@ -1026,7 +1028,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
* Digest */
result = Curl_input_digest(data, proxy, auth);
if(result) {
- infof(data, "Authentication problem. Ignoring this.\n");
+ infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
}
}
@@ -1042,7 +1044,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
anyway, which basically means our name+password isn't
valid. */
authp->avail = CURLAUTH_NONE;
- infof(data, "Authentication problem. Ignoring this.\n");
+ infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
}
}
@@ -1055,7 +1057,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
/* We asked for Bearer authentication but got a 40X back
anyway, which basically means our token isn't valid. */
authp->avail = CURLAUTH_NONE;
- infof(data, "Authentication problem. Ignoring this.\n");
+ infof(data, "Authentication problem. Ignoring this.");
data->state.authproblem = TRUE;
}
}
@@ -1177,6 +1179,7 @@ static size_t readmoredata(char *buffer,
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(data->set.max_send_speed &&
+ (data->set.max_send_speed < (curl_off_t)fullsize) &&
(data->set.max_send_speed < http->postsize))
/* speed limit */
fullsize = (size_t)data->set.max_send_speed;
@@ -1537,38 +1540,35 @@ static int http_getsock_do(struct Curl_easy *data,
#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{
- char proxy_header[128];
struct dynbuf req;
CURLcode result;
- char tcp_version[5];
+ const char *tcp_version;
DEBUGASSERT(data->conn);
+ Curl_dyn_init(&req, DYN_HAXPROXY);
- /* Emit the correct prefix for IPv6 */
- if(data->conn->bits.ipv6) {
- strcpy(tcp_version, "TCP6");
- }
+#ifdef USE_UNIX_SOCKETS
+ if(data->conn->unix_domain_socket)
+ /* the buffer is large enough to hold this! */
+ result = Curl_dyn_add(&req, "PROXY UNKNOWN\r\n");
else {
- strcpy(tcp_version, "TCP4");
- }
-
- msnprintf(proxy_header,
- sizeof(proxy_header),
- "PROXY %s %s %s %i %i\r\n",
- tcp_version,
- data->info.conn_local_ip,
- data->info.conn_primary_ip,
- data->info.conn_local_port,
- data->info.conn_primary_port);
-
- Curl_dyn_init(&req, DYN_HAXPROXY);
+#endif
+ /* Emit the correct prefix for IPv6 */
+ tcp_version = data->conn->bits.ipv6 ? "TCP6" : "TCP4";
- result = Curl_dyn_add(&req, proxy_header);
- if(result)
- return result;
+ result = Curl_dyn_addf(&req, "PROXY %s %s %s %i %i\r\n",
+ tcp_version,
+ data->info.conn_local_ip,
+ data->info.conn_primary_ip,
+ data->info.conn_local_port,
+ data->info.conn_primary_port);
- result = Curl_buffer_send(&req, data, &data->info.request_size,
- 0, FIRSTSOCKET);
+#ifdef USE_UNIX_SOCKETS
+ }
+#endif
+ if(!result)
+ result = Curl_buffer_send(&req, data, &data->info.request_size,
+ 0, FIRSTSOCKET);
return result;
}
#endif
@@ -1588,7 +1588,7 @@ static CURLcode https_connecting(struct Curl_easy *data, bool *done)
#endif
/* perform SSL initialization for this socket */
- result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET, done);
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done);
if(result)
connclose(conn, "Failed HTTPS connection");
@@ -1669,8 +1669,8 @@ CURLcode Curl_http_done(struct Curl_easy *data,
* - if any server previously contacted to handle this request only supports
* 1.0.
*/
-static bool use_http_1_1plus(const struct Curl_easy *data,
- const struct connectdata *conn)
+bool Curl_use_http_1_1plus(const struct Curl_easy *data,
+ const struct connectdata *conn)
{
if((data->state.httpversion == 10) || (conn->httpversion == 10))
return FALSE;
@@ -1696,7 +1696,7 @@ static const char *get_http_string(const struct Curl_easy *data,
return "2";
#endif
- if(use_http_1_1plus(data, conn))
+ if(Curl_use_http_1_1plus(data, conn))
return "1.1";
return "1.0";
@@ -1711,7 +1711,7 @@ static CURLcode expect100(struct Curl_easy *data,
CURLcode result = CURLE_OK;
data->state.expect100header = FALSE; /* default to false unless it is set
to TRUE below */
- if(!data->state.disableexpect && use_http_1_1plus(data, conn) &&
+ if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
(conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
@@ -2348,7 +2348,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
- else if(use_http_1_1plus(data, conn)) {
+ else if(Curl_use_http_1_1plus(data, conn)) {
if(conn->httpversion < 20)
/* HTTP, upload, unknown file size and not HTTP 1.0 */
data->req.upload_chunky = TRUE;
@@ -2711,14 +2711,16 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
int count = 0;
if(data->cookies && data->state.cookie_engine) {
+ const char *host = data->state.aptr.cookiehost ?
+ data->state.aptr.cookiehost : conn->host.name;
+ const bool secure_context =
+ conn->handler->protocol&CURLPROTO_HTTPS ||
+ strcasecompare("localhost", host) ||
+ !strcmp(host, "127.0.0.1") ||
+ !strcmp(host, "[::1]") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- co = Curl_cookie_getlist(data->cookies,
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:
- conn->host.name,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
+ co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
+ secure_context);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
if(co) {
@@ -2901,6 +2903,20 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
{
struct SingleRequest *k = &data->req;
DEBUGASSERT(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP));
+ if(data->req.ignore_cl) {
+ k->size = k->maxdownload = -1;
+ }
+ else if(k->size != -1) {
+ /* We wait until after all headers have been received to set this so that
+ we know for sure Content-Length is valid. */
+ if(data->set.max_filesize &&
+ k->size > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+ Curl_pgrsSetDownloadSize(data, k->size);
+ }
+
if(data->req.newurl) {
if(conn->bits.close) {
/* Abort after the headers if "follow Location" is set
@@ -2912,7 +2928,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
/* We have a new url to load, but since we want to be able to re-use this
connection properly, we read the full response in "ignore more" */
k->ignorebody = TRUE;
- infof(data, "Ignoring the response-body\n");
+ infof(data, "Ignoring the response-body");
}
if(data->state.resume_from && !k->content_range &&
(data->state.httpreq == HTTPREQ_GET) &&
@@ -2947,7 +2963,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
/* We're simulating a http 304 from server so we return
what should have been returned from the server */
data->info.httpcode = 304;
- infof(data, "Simulate a HTTP 304 response!\n");
+ infof(data, "Simulate a HTTP 304 response!");
/* we abort the transfer before it is completed == we ruin the
re-use ability. Close the connection */
connclose(conn, "Simulated 304 handling");
@@ -2958,6 +2974,39 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
return CURLE_OK;
}
+#ifdef HAVE_LIBZ
+CURLcode Curl_transferencode(struct Curl_easy *data)
+{
+ if(!Curl_checkheaders(data, "TE") &&
+ data->set.http_transfer_encoding) {
+ /* When we are to insert a TE: header in the request, we must also insert
+ TE in a Connection: header, so we need to merge the custom provided
+ Connection: header and prevent the original to get sent. Note that if
+ the user has inserted his/her own TE: header we don't do this magic
+ but then assume that the user will handle it all! */
+ char *cptr = Curl_checkheaders(data, "Connection");
+#define TE_HEADER "TE: gzip\r\n"
+
+ Curl_safefree(data->state.aptr.te);
+
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ /* Create the (updated) Connection: header */
+ data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+
+ free(cptr);
+ if(!data->state.aptr.te)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+#endif
+
#ifndef USE_HYPER
/*
* Curl_http() gets called from the generic multi_do() function when a HTTP
@@ -3004,11 +3053,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
/* We don't support HTTP/2 proxies yet. Also it's debatable
whether or not this setting should apply to HTTP/2 proxies. */
- infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+ infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
break;
}
#endif
- DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
+ DEBUGF(infof(data, "HTTP/2 over clean TCP"));
conn->httpversion = 20;
result = Curl_http2_switched(data, NULL, 0);
@@ -3074,33 +3123,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
-
- if(!Curl_checkheaders(data, "TE") &&
- data->set.http_transfer_encoding) {
- /* When we are to insert a TE: header in the request, we must also insert
- TE in a Connection: header, so we need to merge the custom provided
- Connection: header and prevent the original to get sent. Note that if
- the user has inserted his/her own TE: header we don't do this magic
- but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(data, "Connection");
-#define TE_HEADER "TE: gzip\r\n"
-
- Curl_safefree(data->state.aptr.te);
-
- if(cptr) {
- cptr = Curl_copy_header_value(cptr);
- if(!cptr)
- return CURLE_OUT_OF_MEMORY;
- }
-
- /* Create the (updated) Connection: header */
- data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
- cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
-
- free(cptr);
- if(!data->state.aptr.te)
- return CURLE_OUT_OF_MEMORY;
- }
+ result = Curl_transferencode(data);
+ if(result)
+ return result;
#endif
result = Curl_http_body(data, conn, httpreq, &te);
@@ -3253,7 +3278,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* already sent the entire request body, mark the "upload" as
complete */
infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
- " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ " out of %" CURL_FORMAT_CURL_OFF_T " bytes",
data->req.writebytecount, http->postsize);
data->req.upload_done = TRUE;
data->req.keepon &= ~KEEP_SEND; /* we're done writing */
@@ -3392,17 +3417,8 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
NULL, 10, &contentlength);
if(offt == CURL_OFFT_OK) {
- if(data->set.max_filesize &&
- contentlength > data->set.max_filesize) {
- failf(data, "Maximum file size exceeded");
- return CURLE_FILESIZE_EXCEEDED;
- }
k->size = contentlength;
k->maxdownload = k->size;
- /* we set the progress download size already at this point
- just to make it easier for apps/callbacks to extract this
- info as soon as possible */
- Curl_pgrsSetDownloadSize(data, k->size);
}
else if(offt == CURL_OFFT_FLOW) {
/* out of range */
@@ -3411,7 +3427,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
return CURLE_FILESIZE_EXCEEDED;
}
streamclose(conn, "overflow content-length");
- infof(data, "Overflow Content-Length: value!\n");
+ infof(data, "Overflow Content-Length: value!");
}
else {
/* negative or just rubbish - bad HTTP */
@@ -3443,7 +3459,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
* Default action for 1.0 is to close.
*/
connkeep(conn, "Proxy-Connection keep-alive"); /* don't close */
- infof(data, "HTTP/1.0 proxy connection set to keep alive!\n");
+ infof(data, "HTTP/1.0 proxy connection set to keep alive!");
}
else if((conn->httpversion == 11) &&
conn->bits.httpproxy &&
@@ -3453,7 +3469,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
* close down after this transfer.
*/
connclose(conn, "Proxy-Connection: asked to close after done");
- infof(data, "HTTP/1.1 proxy connection set close!\n");
+ infof(data, "HTTP/1.1 proxy connection set close!");
}
#endif
else if((conn->httpversion == 10) &&
@@ -3465,7 +3481,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
*
* [RFC2068, section 19.7.1] */
connkeep(conn, "Connection keep-alive");
- infof(data, "HTTP/1.0 connection set to keep alive!\n");
+ infof(data, "HTTP/1.0 connection set to keep alive!");
}
else if(Curl_compareheader(headp, "Connection:", "close")) {
/*
@@ -3493,6 +3509,12 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
TRUE);
if(result)
return result;
+ if(!k->chunk) {
+ /* if this isn't chunked, only close can signal the end of this transfer
+ as Content-Length is said not to be trusted for transfer-encoding! */
+ connclose(conn, "HTTP/1.1 transfer-encoding without chunks");
+ k->ignore_cl = TRUE;
+ }
}
else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
data->set.str[STRING_ENCODING]) {
@@ -3555,18 +3577,21 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
#if !defined(CURL_DISABLE_COOKIES)
else if(data->cookies && data->state.cookie_engine &&
checkprefix("Set-Cookie:", headp)) {
+ /* If there is a custom-set Host: name, use it here, or else use real peer
+ host name. */
+ const char *host = data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:conn->host.name;
+ const bool secure_context =
+ conn->handler->protocol&CURLPROTO_HTTPS ||
+ strcasecompare("localhost", host) ||
+ !strcmp(host, "127.0.0.1") ||
+ !strcmp(host, "[::1]") ? TRUE : FALSE;
+
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
- Curl_cookie_add(data,
- data->cookies, TRUE, FALSE,
- headp + strlen("Set-Cookie:"),
- /* If there is a custom-set Host: name, use it
- here, or else use real peer host name. */
- data->state.aptr.cookiehost?
- data->state.aptr.cookiehost:conn->host.name,
- data->state.up.path,
- (conn->handler->protocol&CURLPROTO_HTTPS)?
- TRUE:FALSE);
+ Curl_cookie_add(data, data->cookies, TRUE, FALSE,
+ headp + strlen("Set-Cookie:"), host,
+ data->state.up.path, secure_context);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
#endif
@@ -3646,10 +3671,10 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
Curl_hsts_parse(data->hsts, data->state.up.hostname,
headp + strlen("Strict-Transport-Security:"));
if(check)
- infof(data, "Illegal STS header skipped\n");
+ infof(data, "Illegal STS header skipped");
#ifdef DEBUGBUILD
else
- infof(data, "Parsed STS header fine (%zu entries)\n",
+ infof(data, "Parsed STS header fine (%zu entries)",
data->hsts->list.size);
#endif
}
@@ -3719,12 +3744,12 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
/* Default action for HTTP/1.0 must be to close, unless
we get one of those fancy headers that tell us the
server keeps it open for us! */
- infof(data, "HTTP 1.0, assume close after body\n");
+ infof(data, "HTTP 1.0, assume close after body");
connclose(conn, "HTTP/1.0 close after body");
}
else if(conn->httpversion == 20 ||
(k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
- DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
+ DEBUGF(infof(data, "HTTP/2 found, allow multiplexing"));
/* HTTP/2 cannot avoid multiplexing since it is a core functionality
of the protocol */
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
@@ -3733,7 +3758,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
!conn->bits.close) {
/* If HTTP version is >= 1.1 and connection is persistent */
DEBUGF(infof(data,
- "HTTP 1.1 or later with persistent connection\n"));
+ "HTTP 1.1 or later with persistent connection"));
}
k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
@@ -3911,7 +3936,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* Switching Protocols */
if(k->upgr101 == UPGR101_REQUESTED) {
/* Switching to HTTP/2 */
- infof(data, "Received 101\n");
+ infof(data, "Received 101");
k->upgr101 = UPGR101_RECEIVED;
/* we'll get more headers (HTTP/2 response) */
@@ -3951,7 +3976,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
assume that the server will close the connection to
signal the end of the document. */
infof(data, "no chunk, no close, no size. Assume close to "
- "signal end\n");
+ "signal end");
streamclose(conn, "HTTP: No end-of-message indicator");
}
}
@@ -3964,7 +3989,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
(conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
((data->req.httpcode == 407) &&
(conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
- infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+ infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
data->state.authproblem = TRUE;
}
#endif
@@ -3974,7 +3999,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
(conn->http_negotiate_state == GSS_AUTHRECV)) ||
((data->req.httpcode == 407) &&
(conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
- infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+ infof(data, "Connection closure while negotiating auth (HTTP 1.0?)");
data->state.authproblem = TRUE;
}
if((conn->http_negotiate_state == GSS_AUTHDONE) &&
@@ -4054,21 +4079,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if((k->httpcode == 417) && data->state.expect100header) {
/* 417 Expectation Failed - try again without the Expect
header */
- infof(data, "Got 417 while waiting for a 100\n");
+ infof(data, "Got 417 while waiting for a 100");
data->state.disableexpect = TRUE;
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->state.url);
Curl_done_sending(data, k);
}
else if(data->set.http_keep_sending_on_error) {
- infof(data, "HTTP error before end of send, keep sending\n");
+ infof(data, "HTTP error before end of send, keep sending");
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
}
}
else {
- infof(data, "HTTP error before end of send, stop sending\n");
+ infof(data, "HTTP error before end of send, stop sending");
streamclose(conn, "Stop sending data before everything sent");
result = Curl_done_sending(data, k);
if(result)
@@ -4088,7 +4113,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(conn->bits.rewindaftersend) {
/* We rewind after a complete send, so thus we continue
sending now */
- infof(data, "Keep sending data to get tossed away!\n");
+ infof(data, "Keep sending data to get tossed away!");
k->keepon |= KEEP_SEND;
}
}
@@ -4201,18 +4226,20 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* https://tools.ietf.org/html/rfc7230#section-3.1.2
*
* The response code is always a three-digit number in HTTP as the spec
- * says. We try to allow any number here, but we cannot make
+ * says. We allow any three-digit number here, but we cannot make
* guarantees on future behaviors since it isn't within the protocol.
*/
char separator;
char twoorthree[2];
int httpversion = 0;
+ char digit4 = 0;
nc = sscanf(HEADER1,
- " HTTP/%1d.%1d%c%3d",
+ " HTTP/%1d.%1d%c%3d%c",
&httpversion_major,
&httpversion,
&separator,
- &k->httpcode);
+ &k->httpcode,
+ &digit4);
if(nc == 1 && httpversion_major >= 2 &&
2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
@@ -4221,7 +4248,15 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
separator = ' ';
}
- if((nc == 4) && (' ' == separator)) {
+ /* There can only be a 4th response code digit stored in 'digit4' if
+ all the other fields were parsed and stored first, so nc is 5 when
+ digit4 a digit */
+ else if(ISDIGIT(digit4)) {
+ failf(data, "Unsupported response code in HTTP response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ if((nc >= 4) && (' ' == separator)) {
httpversion += 10 * httpversion_major;
switch(httpversion) {
case 10:
@@ -4243,11 +4278,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(k->upgr101 == UPGR101_RECEIVED) {
/* supposedly upgraded to http2 now */
if(conn->httpversion != 20)
- infof(data, "Lying server, not serving HTTP/2\n");
+ infof(data, "Lying server, not serving HTTP/2");
}
if(conn->httpversion < 20) {
conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
- infof(data, "Mark bundle as not supporting multiuse\n");
+ infof(data, "Mark bundle as not supporting multiuse");
}
}
else if(!nc) {
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index 2a3834ae1..e4ab466c0 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -93,11 +93,14 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
struct connectdata *conn);
CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
char *headp);
+CURLcode Curl_transferencode(struct Curl_easy *data);
CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
Curl_HttpReq httpreq,
const char **teep);
CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *r, Curl_HttpReq httpreq);
+bool Curl_use_http_1_1plus(const struct Curl_easy *data,
+ const struct connectdata *conn);
#ifndef CURL_DISABLE_COOKIES
CURLcode Curl_http_cookies(struct Curl_easy *data,
struct connectdata *conn,
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index f194c18b2..6d63f4363 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -146,12 +146,12 @@ static CURLcode http2_disconnect(struct Curl_easy *data,
(void)data;
#endif
- H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
- H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(data, "HTTP/2 DISCONNECT done"));
return CURLE_OK;
}
@@ -196,11 +196,13 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
if(nread != -1) {
infof(data,
- "%d bytes stray data read before trying h2 connection\n",
+ "%d bytes stray data read before trying h2 connection",
(int)nread);
httpc->nread_inbuf = 0;
httpc->inbuflen = nread;
- (void)h2_process_pending_input(data, httpc, &result);
+ if(h2_process_pending_input(data, httpc, &result) < 0)
+ /* immediate error, considered dead */
+ dead = TRUE;
}
else
/* the read failed so let's say this is dead anyway */
@@ -350,13 +352,12 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
};
/*
- * Store nghttp2 version info in this buffer, Prefix with a space. Return
- * total length written.
+ * Store nghttp2 version info in this buffer.
*/
-int Curl_http2_ver(char *p, size_t len)
+void Curl_http2_ver(char *p, size_t len)
{
nghttp2_info *h2 = nghttp2_version(0);
- return msnprintf(p, len, "nghttp2/%s", h2->version_str);
+ (void)msnprintf(p, len, "nghttp2/%s", h2->version_str);
}
/*
@@ -551,7 +552,7 @@ static int push_promise(struct Curl_easy *data,
const nghttp2_push_promise *frame)
{
int rv; /* one of the CURL_PUSH_* defines */
- H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
+ H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!",
frame->promised_stream_id));
if(data->multi->push_cb) {
struct HTTP *stream;
@@ -563,7 +564,7 @@ static int push_promise(struct Curl_easy *data,
/* clone the parent */
struct Curl_easy *newhandle = duphandle(data);
if(!newhandle) {
- infof(data, "failed to duplicate handle\n");
+ infof(data, "failed to duplicate handle");
rv = CURL_PUSH_DENY; /* FAIL HARD */
goto fail;
}
@@ -571,7 +572,7 @@ static int push_promise(struct Curl_easy *data,
heads.data = data;
heads.frame = frame;
/* ask the application */
- H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!"));
stream = data->req.p.http;
if(!stream) {
@@ -619,7 +620,7 @@ static int push_promise(struct Curl_easy *data,
state with the given connection !*/
rc = Curl_multi_add_perform(data->multi, newhandle, conn);
if(rc) {
- infof(data, "failed to add handle to multi\n");
+ infof(data, "failed to add handle to multi");
http2_stream_free(newhandle->req.p.http);
newhandle->req.p.http = NULL;
Curl_close(&newhandle);
@@ -632,15 +633,17 @@ static int push_promise(struct Curl_easy *data,
frame->promised_stream_id,
newhandle);
if(rv) {
- infof(data, "failed to set user_data for stream %d\n",
+ infof(data, "failed to set user_data for stream %d",
frame->promised_stream_id);
DEBUGASSERT(0);
rv = CURL_PUSH_DENY;
goto fail;
}
+ Curl_dyn_init(&newstream->header_recvbuf, DYN_H2_HEADERS);
+ Curl_dyn_init(&newstream->trailer_recvbuf, DYN_H2_TRAILERS);
}
else {
- H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!"));
rv = CURL_PUSH_DENY;
}
fail:
@@ -676,21 +679,21 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- H2BUGF(infof(data, "Got SETTINGS\n"));
+ H2BUGF(infof(data, "Got SETTINGS"));
httpc->settings.max_concurrent_streams =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
httpc->settings.enable_push =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d",
httpc->settings.max_concurrent_streams));
- H2BUGF(infof(data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(data, "ENABLE_PUSH == %s",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
infof(data,
- "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!",
httpc->settings.max_concurrent_streams);
multi_connchanged(data->multi);
}
@@ -700,19 +703,19 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
if(!data_s) {
H2BUGF(infof(data,
- "No Curl_easy associated with stream: %x\n",
+ "No Curl_easy associated with stream: %x",
stream_id));
return 0;
}
stream = data_s->req.p.http;
if(!stream) {
- H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
+ H2BUGF(infof(data_s, "No proto pointer for stream: %x",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
+ H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x",
frame->hd.type, stream_id));
switch(frame->hd.type) {
@@ -760,7 +763,8 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ncopy);
stream->nread_header_recvbuf += ncopy;
- H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
+ DEBUGASSERT(stream->mem);
+ H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p",
ncopy, stream_id, stream->mem));
stream->len -= ncopy;
@@ -782,13 +786,13 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
if(nghttp2_is_fatal(h2))
return NGHTTP2_ERR_CALLBACK_FAILURE;
else if(rv == CURL_PUSH_ERROROUT) {
- DEBUGF(infof(data_s, "Fail the parent stream (too)\n"));
+ DEBUGF(infof(data_s, "Fail the parent stream (too)"));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
break;
default:
- H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n",
+ H2BUGF(infof(data_s, "Got frame type %x for stream %u!",
frame->hd.type, stream_id));
break;
}
@@ -833,7 +837,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "%zu data received for stream %u "
- "(%zu left in buffer %p, total %zu)\n",
+ "(%zu left in buffer %p, total %zu)",
nread, stream_id,
stream->len, stream->mem,
stream->memlen));
@@ -842,7 +846,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
stream->pausedata = mem + nread;
stream->pauselen = len - nread;
H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
- ", stream %u\n",
+ ", stream %u",
len - nread, stream_id));
data_s->conn->proto.httpc.pause_stream_id = stream_id;
@@ -880,7 +884,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
decided to reject stream (e.g., PUSH_PROMISE). */
return 0;
}
- H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
+ H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u",
nghttp2_http2_strerror(error_code), error_code, stream_id));
stream = data_s->req.p.http;
if(!stream)
@@ -895,15 +899,15 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
/* remove the entry from the hash as the stream is now gone */
rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
if(rv) {
- infof(data_s, "http/2: failed to clear user_data for stream %d!\n",
+ infof(data_s, "http/2: failed to clear user_data for stream %d!",
stream_id);
DEBUGASSERT(0);
}
if(stream_id == httpc->pause_stream_id) {
- H2BUGF(infof(data_s, "Stopped the pause stream!\n"));
+ H2BUGF(infof(data_s, "Stopped the pause stream!"));
httpc->pause_stream_id = 0;
}
- H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ H2BUGF(infof(data_s, "Removed stream %u hash!", stream_id));
stream->stream_id = 0; /* cleared */
}
return 0;
@@ -921,7 +925,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- H2BUGF(infof(data_s, "on_begin_headers() was called\n"));
+ H2BUGF(infof(data_s, "on_begin_headers() was called"));
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
@@ -1049,7 +1053,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(stream->bodystarted) {
/* This is a trailer */
- H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s", namelen, name, valuelen,
value));
result = Curl_dyn_addf(&stream->trailer_recvbuf,
"%.*s: %.*s\r\n", namelen, name,
@@ -1082,7 +1086,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(get_transfer(httpc) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
+ H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)",
stream->status_code, data_s));
return 0;
}
@@ -1106,7 +1110,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(get_transfer(httpc) != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 header: %.*s: %.*s", namelen, name, valuelen,
value));
return 0; /* 0 is successful */
@@ -1156,7 +1160,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
return NGHTTP2_ERR_DEFERRED;
H2BUGF(infof(data_s, "data_source_read_callback: "
- "returns %zu bytes stream %u\n",
+ "returns %zu bytes stream %u",
nread, stream_id));
return nread;
@@ -1223,7 +1227,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
(void)nghttp2_session_send(httpc->h2);
if(http->stream_id == httpc->pause_stream_id) {
- infof(data, "stopped the pause stream!\n");
+ infof(data, "stopped the pause stream!");
httpc->pause_stream_id = 0;
}
}
@@ -1236,7 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
int rv = nghttp2_session_set_stream_user_data(httpc->h2,
http->stream_id, 0);
if(rv) {
- infof(data, "http/2: failed to clear user_data for stream %d!\n",
+ infof(data, "http/2: failed to clear user_data for stream %d!",
http->stream_id);
DEBUGASSERT(0);
}
@@ -1383,7 +1387,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
if(nread == rv) {
H2BUGF(infof(data,
"h2_process_pending_input: All data in connection buffer "
- "processed\n"));
+ "processed"));
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
}
@@ -1391,7 +1395,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
httpc->nread_inbuf += rv;
H2BUGF(infof(data,
"h2_process_pending_input: %zu bytes left in connection "
- "buffer\n",
+ "buffer",
httpc->inbuflen - httpc->nread_inbuf));
}
@@ -1412,7 +1416,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
if(should_close_session(httpc)) {
struct HTTP *stream = data->req.p.http;
H2BUGF(infof(data,
- "h2_process_pending_input: nothing to do in this session\n"));
+ "h2_process_pending_input: nothing to do in this session"));
if(stream->error)
*err = CURLE_HTTP2;
else {
@@ -1456,7 +1460,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data,
struct SingleRequest *k = &data->req;
int rv;
- H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));
+ H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)", data));
/* and attempt to send the pending frames */
rv = h2_session_send(data, h2);
@@ -1495,7 +1499,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
if(stream->error == NGHTTP2_REFUSED_STREAM) {
- H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
+ H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!",
stream->stream_id));
connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
data->state.refused_stream = TRUE;
@@ -1544,7 +1548,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
stream->close_handled = TRUE;
- H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
+ H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close"));
return 0;
}
@@ -1587,7 +1591,7 @@ static int h2_session_send(struct Curl_easy *data,
h2_pri_spec(data, &pri_spec);
- H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
+ H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)",
stream->stream_id, data));
DEBUGASSERT(stream->stream_id != -1);
rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
@@ -1611,7 +1615,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
if(should_close_session(httpc)) {
H2BUGF(infof(data,
- "http2_recv: nothing to do in this session\n"));
+ "http2_recv: nothing to do in this session"));
if(conn->bits.close) {
/* already marked for closure, return OK and we're done */
*err = CURLE_OK;
@@ -1621,10 +1625,6 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- if(stream->closed)
- /* closed overrides paused */
- return http2_handle_stream_close(conn, data, stream, err);
-
/* Nullify here because we call nghttp2_session_send() and they
might refer to the old buffer. */
stream->upload_mem = NULL;
@@ -1645,12 +1645,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
stream->nread_header_recvbuf, ncopy);
stream->nread_header_recvbuf += ncopy;
- H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
+ H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf",
(int)ncopy));
return ncopy;
}
- H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n",
+ H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u",
data, stream->stream_id,
nghttp2_session_get_local_window_size(httpc->h2),
nghttp2_session_get_stream_local_window_size(httpc->h2,
@@ -1658,7 +1658,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
));
if((data->state.drain) && stream->memlen) {
- H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
+ H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)",
stream->memlen, stream->stream_id,
stream->mem, mem));
if(mem != stream->mem) {
@@ -1686,7 +1686,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
stream->pauselen -= nread;
if(stream->pauselen == 0) {
- H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
+ H2BUGF(infof(data, "Unpaused by stream %u", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
httpc->pause_stream_id = 0;
@@ -1704,7 +1704,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
return -1;
}
}
- H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u",
nread, stream->stream_id));
return nread;
}
@@ -1720,7 +1720,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
if(stream->closed)
/* closed overrides paused */
return 0;
- H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
+ H2BUGF(infof(data, "stream %x is paused, pause id: %x",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
@@ -1758,12 +1758,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- H2BUGF(infof(data, "end of stream\n"));
+ H2BUGF(infof(data, "end of stream"));
*err = CURLE_OK;
return 0;
}
- H2BUGF(infof(data, "nread=%zd\n", nread));
+ H2BUGF(infof(data, "nread=%zd", nread));
httpc->inbuflen = nread;
@@ -1772,7 +1772,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
else {
nread = httpc->inbuflen - httpc->nread_inbuf;
(void)nread; /* silence warning, used in debug */
- H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
+ H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd",
nread));
}
@@ -1781,14 +1781,14 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
- H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns %zd for stream %u",
retlen, stream->stream_id));
stream->memlen = 0;
if(httpc->pause_stream_id == stream->stream_id) {
/* data for this stream is returned now, but this stream caused a pause
already so we need it called again asap */
- H2BUGF(infof(data, "Data returned for PAUSED stream %u\n",
+ H2BUGF(infof(data, "Data returned for PAUSED stream %u",
stream->stream_id));
}
else if(!stream->closed) {
@@ -1803,7 +1803,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex,
if(stream->closed)
return http2_handle_stream_close(conn, data, stream, err);
*err = CURLE_AGAIN;
- H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
+ H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u",
stream->stream_id));
return -1;
}
@@ -1907,11 +1907,11 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
(void)sockindex;
- H2BUGF(infof(data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(data, "http2_send len=%zu", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
- infof(data, "stream %d closed\n", stream->stream_id);
+ infof(data, "stream %d closed", stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
@@ -1940,7 +1940,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
stream->upload_len = 0;
if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session"));
*err = CURLE_HTTP2;
return -1;
}
@@ -1953,7 +1953,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id);
}
- H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(data, "http2_send returns %zu for stream %u", len,
stream->stream_id));
return len;
}
@@ -2116,7 +2116,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- H2BUGF(infof(data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(data, "h2 header: %.*s:%.*s",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
@@ -2124,13 +2124,13 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
if(acc > MAX_ACC) {
infof(data, "http2_send: Warning: The cumulative length of all "
"headers exceeds %d bytes and that could cause the "
- "stream to be rejected.\n", MAX_ACC);
+ "stream to be rejected.", MAX_ACC);
}
}
h2_pri_spec(data, &pri_spec);
- H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n",
+ H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)",
nghttp2_session_check_request_allowed(h2), (void *)data));
switch(data->state.httpreq) {
@@ -2158,20 +2158,20 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
if(stream_id < 0) {
H2BUGF(infof(data,
- "http2_send() nghttp2_submit_request error (%s)%d\n",
+ "http2_send() nghttp2_submit_request error (%s)%d",
nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
return -1;
}
- infof(data, "Using Stream ID: %x (easy handle %p)\n",
+ infof(data, "Using Stream ID: %x (easy handle %p)",
stream_id, (void *)data);
stream->stream_id = stream_id;
rv = h2_session_send(data, h2);
if(rv) {
H2BUGF(infof(data,
- "http2_send() nghttp2_session_send error (%s)%d\n",
+ "http2_send() nghttp2_session_send error (%s)%d",
nghttp2_strerror(rv), rv));
*err = CURLE_SEND_ERROR;
@@ -2179,7 +2179,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
}
if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_send: nothing to do in this session"));
*err = CURLE_HTTP2;
return -1;
}
@@ -2215,6 +2215,16 @@ CURLcode Curl_http2_setup(struct Curl_easy *data,
Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);
+ stream->upload_left = 0;
+ stream->upload_mem = NULL;
+ stream->upload_len = 0;
+ stream->mem = data->state.buffer;
+ stream->len = data->set.buffer_size;
+
+ multi_connchanged(data->multi);
+ /* below this point only connection related inits are done, which only needs
+ to be done once per connection */
+
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2))
return CURLE_OK; /* already done */
@@ -2230,12 +2240,11 @@ CURLcode Curl_http2_setup(struct Curl_easy *data,
return result;
}
- infof(data, "Using HTTP2, server supports multi-use\n");
- stream->upload_left = 0;
- stream->upload_mem = NULL;
- stream->upload_len = 0;
- stream->mem = data->state.buffer;
- stream->len = data->set.buffer_size;
+ infof(data, "Using HTTP2, server supports multiplexing");
+
+ conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ conn->httpversion = 20;
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
@@ -2243,12 +2252,7 @@ CURLcode Curl_http2_setup(struct Curl_easy *data,
httpc->pause_stream_id = 0;
httpc->drain_total = 0;
- conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- conn->httpversion = 20;
- conn->bundle->multiuse = BUNDLE_MULTIPLEX;
-
- infof(data, "Connection state changed (HTTP/2 confirmed)\n");
- multi_connchanged(data->multi);
+ infof(data, "Connection state changed (HTTP/2 confirmed)");
return CURLE_OK;
}
@@ -2287,7 +2291,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
stream->stream_id,
data);
if(rv) {
- infof(data, "http/2: failed to set user_data for stream %d!\n",
+ infof(data, "http/2: failed to set user_data for stream %d!",
stream->stream_id);
DEBUGASSERT(0);
}
@@ -2327,7 +2331,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
}
infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
- " after upgrade: len=%zu\n",
+ " after upgrade: len=%zu",
nread);
if(nread)
@@ -2337,15 +2341,8 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
DEBUGASSERT(httpc->nread_inbuf == 0);
- /* Good enough to call it an end once the remaining payload is copied to the
- * connection buffer.
- * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately
- * following the protocol switch other than waiting for the client-side
- * connection preface. If h2_process_pending_input is invoked here to parse
- * the remaining payload, stream 1 would be marked as closed too early and
- * thus ignored in http2_recv (following 252790c53).
- * The logic in lib/http.c and lib/transfer.c guarantees a following
- * http2_recv would be invoked very soon. */
+ if(-1 == h2_process_pending_input(data, httpc, &result))
+ return CURLE_HTTP2;
return CURLE_OK;
}
@@ -2378,7 +2375,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
if(rv)
return CURLE_SEND_ERROR;
- DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n",
+ DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u",
window, stream->stream_id));
#ifdef DEBUGBUILD
@@ -2387,7 +2384,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
uint32_t window2 =
nghttp2_session_get_stream_local_window_size(httpc->h2,
stream->stream_id);
- DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n",
+ DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u",
window2, stream->stream_id));
}
#endif
diff --git a/Utilities/cmcurl/lib/http2.h b/Utilities/cmcurl/lib/http2.h
index 21e2c086a..d6986d97f 100644
--- a/Utilities/cmcurl/lib/http2.h
+++ b/Utilities/cmcurl/lib/http2.h
@@ -32,10 +32,9 @@
#define DEFAULT_MAX_CONCURRENT_STREAMS 100
/*
- * Store nghttp2 version info in this buffer, Prefix with a space. Return
- * total length written.
+ * Store nghttp2 version info in this buffer.
*/
-int Curl_http2_ver(char *p, size_t len);
+void Curl_http2_ver(char *p, size_t len);
const char *Curl_http2_strerror(uint32_t err);
diff --git a/Utilities/cmcurl/lib/http_aws_sigv4.c b/Utilities/cmcurl/lib/http_aws_sigv4.c
index a04b46a35..02663abd6 100644
--- a/Utilities/cmcurl/lib/http_aws_sigv4.c
+++ b/Utilities/cmcurl/lib/http_aws_sigv4.c
@@ -126,7 +126,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
tmp1 = strchr(tmp0, ':');
len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
if(len < 1) {
- infof(data, "first provider can't be empty\n");
+ infof(data, "first provider can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
@@ -145,7 +145,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
tmp1 = strchr(tmp0, ':');
len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
if(len < 1) {
- infof(data, "second provider can't be empty\n");
+ infof(data, "second provider can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
@@ -165,7 +165,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
tmp1 = strchr(tmp0, ':');
len = tmp1 ? (size_t)(tmp1 - tmp0) : strlen(tmp0);
if(len < 1) {
- infof(data, "region can't be empty\n");
+ infof(data, "region can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
@@ -182,7 +182,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
goto fail;
}
if(strlen(service) < 1) {
- infof(data, "service can't be empty\n");
+ infof(data, "service can't be empty");
ret = CURLE_BAD_FUNCTION_ARGUMENT;
goto fail;
}
@@ -203,7 +203,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
tmp1 = strchr(tmp0, '.');
len = tmp1 - tmp0;
if(!tmp1 || len < 1) {
- infof(data, "service missing in parameters or hostname\n");
+ infof(data, "service missing in parameters or hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
@@ -218,7 +218,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
tmp1 = strchr(tmp0, '.');
len = tmp1 - tmp0;
if(!tmp1 || len < 1) {
- infof(data, "region missing in parameters or hostname\n");
+ infof(data, "region missing in parameters or hostname");
ret = CURLE_URL_MALFORMAT;
goto fail;
}
diff --git a/Utilities/cmcurl/lib/http_digest.c b/Utilities/cmcurl/lib/http_digest.c
index 049b232e0..34bb5a8e0 100644
--- a/Utilities/cmcurl/lib/http_digest.c
+++ b/Utilities/cmcurl/lib/http_digest.c
@@ -146,7 +146,8 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
tmp = strchr((char *)uripath, '?');
if(tmp) {
size_t urilen = tmp - (char *)uripath;
- path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+ /* typecast is fine here since the value is always less than 32 bits */
+ path = (unsigned char *) aprintf("%.*s", (int)urilen, uripath);
}
}
if(!tmp)
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index 68cce1bbb..5f764dc13 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -89,7 +89,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
neg_ctx->havenegdata = len != 0;
if(!len) {
if(state == GSS_AUTHSUCC) {
- infof(data, "Negotiate auth restarted\n");
+ infof(data, "Negotiate auth restarted");
Curl_http_auth_cleanup_negotiate(conn);
}
else if(state != GSS_AUTHNONE) {
@@ -142,11 +142,11 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data,
}
if(neg_ctx->noauthpersist ||
- (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
+ (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
infof(data, "Curl_output_negotiate, "
- "no persistent authentication: cleanup existing context");
+ "no persistent authentication: cleanup existing context");
Curl_http_auth_cleanup_negotiate(conn);
}
if(!neg_ctx->context) {
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index e200fdb1d..627a11c5a 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -100,17 +100,17 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data,
}
else {
if(*state == NTLMSTATE_LAST) {
- infof(data, "NTLM auth restarted\n");
+ infof(data, "NTLM auth restarted");
Curl_http_auth_cleanup_ntlm(conn);
}
else if(*state == NTLMSTATE_TYPE3) {
- infof(data, "NTLM handshake rejected\n");
+ infof(data, "NTLM handshake rejected");
Curl_http_auth_cleanup_ntlm(conn);
*state = NTLMSTATE_NONE;
return CURLE_REMOTE_ACCESS_DENIED;
}
else if(*state >= NTLMSTATE_TYPE1) {
- infof(data, "NTLM handshake failure (internal error)\n");
+ infof(data, "NTLM handshake failure (internal error)");
return CURLE_REMOTE_ACCESS_DENIED;
}
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index a3a62c1ca..58489abec 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -61,7 +61,7 @@ static CURLcode https_proxy_connect(struct Curl_easy *data, int sockindex)
if(!conn->bits.proxy_ssl_connected[sockindex]) {
/* perform SSL initialization for this socket */
result =
- Curl_ssl_connect_nonblocking(data, conn, sockindex,
+ Curl_ssl_connect_nonblocking(data, conn, TRUE, sockindex,
&conn->bits.proxy_ssl_connected[sockindex]);
if(result)
/* a failed connection is marked for closure to prevent (bad) re-use or
@@ -129,13 +129,13 @@ CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex)
bool Curl_connect_complete(struct connectdata *conn)
{
return !conn->connect_state ||
- (conn->connect_state->tunnel_state == TUNNEL_COMPLETE);
+ (conn->connect_state->tunnel_state >= TUNNEL_COMPLETE);
}
bool Curl_connect_ongoing(struct connectdata *conn)
{
return conn->connect_state &&
- (conn->connect_state->tunnel_state != TUNNEL_COMPLETE);
+ (conn->connect_state->tunnel_state <= TUNNEL_COMPLETE);
}
/* when we've sent a CONNECT to a proxy, we should rather either wait for the
@@ -148,7 +148,7 @@ int Curl_connect_getsock(struct connectdata *conn)
DEBUGASSERT(conn->connect_state);
http = &conn->connect_state->http_proxy;
- if(http->sending)
+ if(http->sending == HTTPSEND_REQUEST)
return GETSOCK_WRITESOCK(0);
return GETSOCK_READSOCK(0);
@@ -169,7 +169,7 @@ static CURLcode connect_init(struct Curl_easy *data, bool reinit)
s = calloc(1, sizeof(struct http_connect_state));
if(!s)
return CURLE_OUT_OF_MEMORY;
- infof(data, "allocate connect buffer!\n");
+ infof(data, "allocate connect buffer!");
conn->connect_state = s;
Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
@@ -202,13 +202,16 @@ static void connect_done(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
struct http_connect_state *s = conn->connect_state;
- s->tunnel_state = TUNNEL_COMPLETE;
- Curl_dyn_free(&s->rcvbuf);
- Curl_dyn_free(&s->req);
+ if(s->tunnel_state != TUNNEL_EXIT) {
+ s->tunnel_state = TUNNEL_EXIT;
+ Curl_dyn_free(&s->rcvbuf);
+ Curl_dyn_free(&s->req);
- /* retore the protocol pointer */
- data->req.p.http = s->prot_save;
- infof(data, "CONNECT phase completed!\n");
+ /* retore the protocol pointer */
+ data->req.p.http = s->prot_save;
+ s->prot_save = NULL;
+ infof(data, "CONNECT phase completed!");
+ }
}
static CURLcode CONNECT_host(struct Curl_easy *data,
@@ -243,11 +246,11 @@ static CURLcode CONNECT_host(struct Curl_easy *data,
return CURLE_OK;
}
+#ifndef USE_HYPER
static CURLcode CONNECT(struct Curl_easy *data,
int sockindex,
const char *hostname,
int remote_port)
-#ifndef USE_HYPER
{
int subversion = 0;
struct SingleRequest *k = &data->req;
@@ -275,7 +278,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
char *hostheader = NULL;
char *host = NULL;
- infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
+ infof(data, "Establish HTTP proxy tunnel to %s:%d",
hostname, remote_port);
/* This only happens if we've looped here due to authentication
@@ -297,32 +300,27 @@ static CURLcode CONNECT(struct Curl_easy *data,
hostheader, TRUE);
if(!result) {
- const char *proxyconn = "";
- const char *useragent = "";
const char *httpv =
(conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
- if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection"))
- proxyconn = "Proxy-Connection: Keep-Alive\r\n";
-
- if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
- data->set.str[STRING_USERAGENT])
- useragent = data->state.aptr.uagent;
-
result =
Curl_dyn_addf(req,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
- "%s" /* Proxy-Authorization */
- "%s" /* User-Agent */
- "%s", /* Proxy-Connection */
+ "%s", /* Proxy-Authorization */
hostheader,
httpv,
host?host:"",
data->state.aptr.proxyuserpwd?
- data->state.aptr.proxyuserpwd:"",
- useragent,
- proxyconn);
+ data->state.aptr.proxyuserpwd:"");
+
+ if(!result && !Curl_checkProxyheaders(data, conn, "User-Agent") &&
+ data->set.str[STRING_USERAGENT])
+ result = Curl_dyn_addf(req, "User-Agent: %s\r\n",
+ data->set.str[STRING_USERAGENT]);
+
+ if(!result && !Curl_checkProxyheaders(data, conn, "Proxy-Connection"))
+ result = Curl_dyn_add(req, "Proxy-Connection: Keep-Alive\r\n");
if(!result)
result = Curl_add_custom_headers(data, TRUE, req);
@@ -387,6 +385,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
k->upload_fromhere += bytes_written;
return result;
}
+ http->sending = HTTPSEND_NADA;
/* if nothing left to send, continue */
}
{ /* READING RESPONSE PHASE */
@@ -416,7 +415,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
/* proxy auth was requested and there was proxy auth available,
then deem this as "mere" proxy disconnect */
conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Proxy CONNECT connection closed\n");
+ infof(data, "Proxy CONNECT connection closed");
}
else {
error = SELECT_ERROR;
@@ -451,7 +450,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
- infof(data, "chunk reading DONE\n");
+ infof(data, "chunk reading DONE");
s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
@@ -510,13 +509,13 @@ static CURLcode CONNECT(struct Curl_easy *data,
if(s->cl) {
infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
- " bytes of response-body\n", s->cl);
+ " bytes of response-body", s->cl);
}
else if(s->chunked_encoding) {
CHUNKcode r;
CURLcode extra;
- infof(data, "Ignore chunked response-body\n");
+ infof(data, "Ignore chunked response-body");
/* We set ignorebody true here since the chunked decoder
function will acknowledge that. Pay attention so that this is
@@ -533,7 +532,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
&extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
- infof(data, "chunk reading DONE\n");
+ infof(data, "chunk reading DONE");
s->keepon = KEEPON_DONE;
/* we did the full CONNECT treatment, go to COMPLETE */
s->tunnel_state = TUNNEL_COMPLETE;
@@ -579,7 +578,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
/* A client MUST ignore any Content-Length or Transfer-Encoding
header fields received in a successful response to CONNECT.
"Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */
- infof(data, "Ignoring Content-Length in CONNECT %03d response\n",
+ infof(data, "Ignoring Content-Length in CONNECT %03d response",
k->httpcode);
}
else {
@@ -595,11 +594,11 @@ static CURLcode CONNECT(struct Curl_easy *data,
header fields received in a successful response to CONNECT.
"Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */
infof(data, "Ignoring Transfer-Encoding in "
- "CONNECT %03d response\n", k->httpcode);
+ "CONNECT %03d response", k->httpcode);
}
else if(Curl_compareheader(linep,
"Transfer-Encoding:", "chunked")) {
- infof(data, "CONNECT responded chunked\n");
+ infof(data, "CONNECT responded chunked");
s->chunked_encoding = TRUE;
/* init our chunky engine */
Curl_httpchunk_init(data);
@@ -657,7 +656,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
if(data->info.httpproxycode/100 != 2) {
if(s->close_connection && data->req.newurl) {
conn->bits.proxy_connect_closed = TRUE;
- infof(data, "Connect me again please\n");
+ infof(data, "Connect me again please");
connect_done(data);
}
else {
@@ -692,7 +691,7 @@ static CURLcode CONNECT(struct Curl_easy *data,
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
- infof(data, "Proxy replied %d to CONNECT request\n",
+ infof(data, "Proxy replied %d to CONNECT request",
data->info.httpproxycode);
data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
@@ -702,6 +701,10 @@ static CURLcode CONNECT(struct Curl_easy *data,
}
#else
/* The Hyper version of CONNECT */
+static CURLcode CONNECT(struct Curl_easy *data,
+ int sockindex,
+ const char *hostname,
+ int remote_port)
{
struct connectdata *conn = data->conn;
struct hyptransfer *h = &data->hyp;
@@ -740,6 +743,8 @@ static CURLcode CONNECT(struct Curl_easy *data,
hyper_io_set_write(io, Curl_hyper_send);
conn->sockfd = tunnelsocket;
+ data->state.hconnect = TRUE;
+
/* create an executor to poll futures */
if(!h->exec) {
h->exec = hyper_executor_new();
@@ -830,16 +835,26 @@ static CURLcode CONNECT(struct Curl_easy *data,
Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd))
goto error;
- if(data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] &&
- data->state.aptr.uagent &&
- Curl_hyper_header(data, headers, data->state.aptr.uagent))
- goto error;
+ if(!Curl_checkProxyheaders(data, conn, "User-Agent") &&
+ data->set.str[STRING_USERAGENT]) {
+ struct dynbuf ua;
+ Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
+ result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
+ data->set.str[STRING_USERAGENT]);
+ if(result)
+ goto error;
+ if(Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua)))
+ goto error;
+ Curl_dyn_free(&ua);
+ }
if(!Curl_checkProxyheaders(data, conn, "Proxy-Connection") &&
Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"))
goto error;
+ if(Curl_add_custom_headers(data, TRUE, headers))
+ goto error;
+
sendtask = hyper_clientconn_send(client, req);
if(!sendtask) {
failf(data, "hyper_clientconn_send");
@@ -875,7 +890,6 @@ static CURLcode CONNECT(struct Curl_easy *data,
goto error;
if(!done)
break;
- fprintf(stderr, "done\n");
s->tunnel_state = TUNNEL_COMPLETE;
if(h->exec) {
hyper_executor_free(h->exec);
@@ -897,6 +911,33 @@ static CURLcode CONNECT(struct Curl_easy *data,
} while(data->req.newurl);
result = CURLE_OK;
+ if(s->tunnel_state == TUNNEL_COMPLETE) {
+ data->info.httpproxycode = data->req.httpcode;
+ if(data->info.httpproxycode/100 != 2) {
+ if(conn->bits.close && data->req.newurl) {
+ conn->bits.proxy_connect_closed = TRUE;
+ infof(data, "Connect me again please");
+ connect_done(data);
+ }
+ else {
+ free(data->req.newurl);
+ data->req.newurl = NULL;
+ /* failure, close this connection to avoid re-use */
+ streamclose(conn, "proxy CONNECT failure");
+ Curl_closesocket(data, conn, conn->sock[sockindex]);
+ conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
+
+ /* to back to init state */
+ s->tunnel_state = TUNNEL_INIT;
+
+ if(!conn->bits.proxy_connect_closed) {
+ failf(data, "Received HTTP code %d from proxy after CONNECT",
+ data->req.httpcode);
+ result = CURLE_RECV_ERROR;
+ }
+ }
+ }
error:
free(host);
free(hostheader);
@@ -917,7 +958,6 @@ static CURLcode CONNECT(struct Curl_easy *data,
}
return result;
}
-
#endif
void Curl_connect_free(struct Curl_easy *data)
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index f5a4cb07c..cdf8de4fb 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -65,9 +65,10 @@ struct http_connect_state {
} keepon;
curl_off_t cl; /* size of content to read and ignore */
enum {
- TUNNEL_INIT, /* init/default/no tunnel state */
- TUNNEL_CONNECT, /* CONNECT has been sent off */
- TUNNEL_COMPLETE /* CONNECT response received completely */
+ TUNNEL_INIT, /* init/default/no tunnel state */
+ TUNNEL_CONNECT, /* CONNECT has been sent off */
+ TUNNEL_COMPLETE, /* CONNECT response received completely */
+ TUNNEL_EXIT
} tunnel_state;
BIT(chunked_encoding);
BIT(close_connection);
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index d85bcc391..6163899bb 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -74,7 +74,6 @@
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
-#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
@@ -414,7 +413,7 @@ static void state(struct Curl_easy *data, imapstate newstate)
};
if(imapc->state != newstate)
- infof(data, "IMAP %p state change from %s to %s\n",
+ infof(data, "IMAP %p state change from %s to %s",
(void *)imapc, names[imapc->state], names[newstate]);
#endif
@@ -475,8 +474,8 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
{
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
- &imapc->ssldone);
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
+ FIRSTSOCKET, &imapc->ssldone);
if(!result) {
if(imapc->state != IMAP_UPGRADETLS)
@@ -606,7 +605,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
result = imap_perform_login(data, conn);
else {
/* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!");
result = CURLE_LOGIN_DENIED;
}
}
@@ -861,7 +860,7 @@ static CURLcode imap_state_servergreet_resp(struct Curl_easy *data,
/* PREAUTH */
struct imap_conn *imapc = &conn->proto.imapc;
imapc->preauth = TRUE;
- infof(data, "PREAUTH connection, already authenticated!\n");
+ infof(data, "PREAUTH connection, already authenticated!");
}
else if(imapcode != IMAP_RESP_OK) {
failf(data, "Got unexpected imap-server response");
@@ -935,22 +934,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
line += wordlen;
}
}
- else if(imapcode == IMAP_RESP_OK) {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(imapc->tls_supported)
- /* Switch to TLS connection now */
- result = imap_perform_starttls(data, conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = imap_perform_authentication(data, conn);
- else {
- failf(data, "STARTTLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
+ else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+ /* PREAUTH is not compatible with STARTTLS. */
+ if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
+ /* Switch to TLS connection now */
+ result = imap_perform_starttls(data, conn);
}
- else
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
result = imap_perform_authentication(data, conn);
+ else {
+ failf(data, "STARTTLS not available.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
else
result = imap_perform_authentication(data, conn);
@@ -968,6 +963,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.imapc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(imapcode != IMAP_RESP_OK) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
@@ -1143,7 +1142,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
}
if(parsed) {
- infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n",
+ infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download",
size);
Curl_pgrsSetDownloadSize(data, size);
@@ -1169,7 +1168,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
data->req.bytecount += chunk;
infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
- " bytes are left for transfer\n", chunk, size - chunk);
+ " bytes are left for transfer", chunk, size - chunk);
/* Have we used the entire cache or just part of it?*/
if(pp->cache_size > chunk) {
@@ -1369,7 +1368,7 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn,
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &imapc->ssldone);
if(result || !imapc->ssldone)
return result;
@@ -1543,7 +1542,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
@@ -1590,7 +1589,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
return result;
}
@@ -1682,11 +1681,11 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done)
CURLcode result = imap_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
result = imap_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -2017,7 +2016,7 @@ static CURLcode imap_parse_url_path(struct Curl_easy *data)
return result;
}
- DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'\n", name, value));
+ DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'", name, value));
/* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and
PARTIAL) stripping of the trailing slash character if it is present.
diff --git a/Utilities/cmcurl/lib/inet_ntop.c b/Utilities/cmcurl/lib/inet_ntop.c
index 4c3e9e4da..b5f9b808a 100644
--- a/Utilities/cmcurl/lib/inet_ntop.c
+++ b/Utilities/cmcurl/lib/inet_ntop.c
@@ -40,7 +40,7 @@
#define INT16SZ 2
/*
- * Format an IPv4 address, more or less like inet_ntoa().
+ * Format an IPv4 address, more or less like inet_ntop().
*
* Returns `dst' (as a const)
* Note:
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index c8c4b6601..659947d9b 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -263,7 +263,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
}
/* We pass NULL as |output_name_type| to avoid a leak. */
gss_display_name(&min, gssname, &output_buffer, NULL);
- Curl_infof(data, "Trying against %s\n", output_buffer.value);
+ infof(data, "Trying against %s", output_buffer.value);
gssresp = GSS_C_NO_BUFFER;
*context = GSS_C_NO_CONTEXT;
@@ -290,7 +290,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
}
if(GSS_ERROR(maj)) {
- Curl_infof(data, "Error creating security context\n");
+ infof(data, "Error creating security context");
ret = AUTH_ERROR;
break;
}
@@ -301,8 +301,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
result = Curl_base64_encode(data, (char *)output_buffer.value,
output_buffer.length, &p, &base64_sz);
if(result) {
- Curl_infof(data, "base64-encoding: %s\n",
- curl_easy_strerror(result));
+ infof(data, "base64-encoding: %s", curl_easy_strerror(result));
ret = AUTH_ERROR;
break;
}
@@ -327,7 +326,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
}
if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
- Curl_infof(data, "Server didn't accept auth data\n");
+ infof(data, "Server didn't accept auth data");
ret = AUTH_ERROR;
break;
}
@@ -629,7 +628,7 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
socket_write(data, fd, cmd_buffer, cmd_size);
socket_write(data, fd, "\r\n", 2);
- infof(data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic,
+ infof(data, "Send: %s%s", prot_level == PROT_PRIVATE?enc:mic,
cmd_buffer);
free(cmd_buffer);
}
@@ -738,7 +737,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
if(!conn->sec_complete) {
infof(data, "Trying to change the protection level after the"
- " completion of the data exchange.\n");
+ " completion of the data exchange.");
return -1;
}
@@ -815,13 +814,13 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
if(mech->init) {
ret = mech->init(conn->app_data);
if(ret) {
- infof(data, "Failed initialization for %s. Skipping it.\n",
+ infof(data, "Failed initialization for %s. Skipping it.",
mech->name);
return CURLE_FAILED_INIT;
}
}
- infof(data, "Trying mechanism %s...\n", mech->name);
+ infof(data, "Trying mechanism %s...", mech->name);
ret = ftp_send_command(data, "AUTH %s", mech->name);
if(ret < 0)
return CURLE_COULDNT_CONNECT;
@@ -830,15 +829,15 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
switch(ret) {
case 504:
infof(data, "Mechanism %s is not supported by the server (server "
- "returned ftp code: 504).\n", mech->name);
+ "returned ftp code: 504).", mech->name);
break;
case 534:
infof(data, "Mechanism %s was rejected by the server (server returned "
- "ftp code: 534).\n", mech->name);
+ "ftp code: 534).", mech->name);
break;
default:
if(ret/100 == 5) {
- infof(data, "server does not support the security extensions\n");
+ infof(data, "server does not support the security extensions");
return CURLE_USE_SSL_FAILED;
}
break;
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index ed1642302..1d9e44cc9 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -296,9 +296,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
char *passwd = NULL;
*done = TRUE; /* unconditionally */
- infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
+ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d",
LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
- infof(data, "LDAP local: %s\n", data->state.url);
+ infof(data, "LDAP local: %s", data->state.url);
#ifdef HAVE_LDAP_URL_PARSE
rc = ldap_url_parse(data->state.url, &ludp);
@@ -314,7 +314,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
/* Get the URL scheme (either ldap or ldaps) */
if(conn->given->flags & PROTOPT_SSL)
ldap_ssl = 1;
- infof(data, "LDAP local: trying to establish %s connection\n",
+ infof(data, "LDAP local: trying to establish %s connection",
ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP)
@@ -366,14 +366,14 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- infof(data, "LDAP local: using %s CA cert '%s'\n",
- (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
- ldap_ca);
+ infof(data, "LDAP local: using %s CA cert '%s'",
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_ca);
rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
if(rc != LDAP_SUCCESS) {
failf(data, "LDAP local: ERROR setting %s CA cert: %s",
- (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
- ldap_err2string(rc));
+ (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
+ ldap_err2string(rc));
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
@@ -409,7 +409,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
- infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca);
+ infof(data, "LDAP local: using PEM CA cert: %s", ldap_ca);
rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
if(rc != LDAP_SUCCESS) {
failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
@@ -718,7 +718,7 @@ quit:
LDAP_TRACE(("Received %d entries\n", num));
}
if(rc == LDAP_SIZELIMIT_EXCEEDED)
- infof(data, "There are more than %d entries\n", num);
+ infof(data, "There are more than %d entries", num);
if(ludp)
ldap_free_urldesc(ludp);
if(server)
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index c651ddf66..e7a428fc2 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -36,8 +36,12 @@
#endif /* USE_OPENSSL */
#ifdef USE_MBEDTLS
-#include <mbedtls/config.h>
#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+#include <mbedtls/mbedtls_config.h>
+#else
+#include <mbedtls/config.h>
+#endif
#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
#define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index 7a24fd8cf..983ed9746 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -33,7 +33,8 @@
#ifdef USE_MBEDTLS
#include <mbedtls/version.h>
-#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
+ (MBEDTLS_VERSION_NUMBER < 0x03000000)
#define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
#endif
#endif /* USE_MBEDTLS */
@@ -85,7 +86,7 @@ typedef mbedtls_md5_context MD5_CTX;
static void MD5_Init(MD5_CTX *ctx)
{
#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_md5_starts(ctx);
+ (void) mbedtls_md5_starts(ctx);
#else
(void) mbedtls_md5_starts_ret(ctx);
#endif
@@ -96,7 +97,7 @@ static void MD5_Update(MD5_CTX *ctx,
unsigned int length)
{
#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_md5_update(ctx, data, length);
+ (void) mbedtls_md5_update(ctx, data, length);
#else
(void) mbedtls_md5_update_ret(ctx, data, length);
#endif
@@ -105,7 +106,7 @@ static void MD5_Update(MD5_CTX *ctx,
static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
{
#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_md5_finish(ctx, digest);
+ (void) mbedtls_md5_finish(ctx, digest);
#else
(void) mbedtls_md5_finish_ret(ctx, digest);
#endif
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 529202686..7a1aec570 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -1017,9 +1017,11 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
if((retcode != -1) && info.max) {
/* we terminate this with a zero byte */
- if(info.max == info.length)
+ if(info.max == info.length) {
/* we're at maximum, scrap the last letter */
info.buffer[-1] = 0;
+ retcode--; /* don't count the nul byte */
+ }
else
info.buffer[0] = 0;
}
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index d88fa737d..fcd40b41e 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data,
mq->sendleftovers = sendleftovers;
mq->nsend = nsend;
}
+ else {
+ mq->sendleftovers = NULL;
+ mq->nsend = 0;
+ }
return result;
}
@@ -143,32 +147,197 @@ static int mqtt_getsock(struct Curl_easy *data,
return GETSOCK_READSOCK(FIRSTSOCKET);
}
+static int mqtt_encode_len(char *buf, size_t len)
+{
+ unsigned char encoded;
+ int i;
+
+ for(i = 0; (len > 0) && (i<4); i++) {
+ encoded = len % 0x80;
+ len /= 0x80;
+ if(len)
+ encoded |= 0x80;
+ buf[i] = encoded;
+ }
+
+ return i;
+}
+
+/* add the passwd to the CONNECT packet */
+static int add_passwd(const char *passwd, const size_t plen,
+ char *pkt, const size_t start, int remain_pos)
+{
+ /* magic number that need to be set properly */
+ const size_t conn_flags_pos = remain_pos + 8;
+ if(plen > 0xffff)
+ return 1;
+
+ /* set password flag */
+ pkt[conn_flags_pos] |= 0x40;
+
+ /* length of password provided */
+ pkt[start] = (char)((plen >> 8) & 0xFF);
+ pkt[start + 1] = (char)(plen & 0xFF);
+ memcpy(&pkt[start + 2], passwd, plen);
+ return 0;
+}
+
+/* add user to the CONN packet */
+static int add_user(const char *username, const size_t ulen,
+ unsigned char *pkt, const size_t start, int remain_pos)
+{
+ /* magic number that need to be set properly */
+ const size_t conn_flags_pos = remain_pos + 8;
+ if(ulen > 0xffff)
+ return 1;
+
+ /* set username flag */
+ pkt[conn_flags_pos] |= 0x80;
+ /* length of username provided */
+ pkt[start] = (unsigned char)((ulen >> 8) & 0xFF);
+ pkt[start + 1] = (unsigned char)(ulen & 0xFF);
+ memcpy(&pkt[start + 2], username, ulen);
+ return 0;
+}
+
+/* add client ID to the CONN packet */
+static int add_client_id(const char *client_id, const size_t client_id_len,
+ char *pkt, const size_t start)
+{
+ if(client_id_len != MQTT_CLIENTID_LEN)
+ return 1;
+ pkt[start] = 0x00;
+ pkt[start + 1] = MQTT_CLIENTID_LEN;
+ memcpy(&pkt[start + 2], client_id, MQTT_CLIENTID_LEN);
+ return 0;
+}
+
+/* Set initial values of CONN packet */
+static int init_connpack(char *packet, char *remain, int remain_pos)
+{
+ /* Fixed header starts */
+ /* packet type */
+ packet[0] = MQTT_MSG_CONNECT;
+ /* remaining length field */
+ memcpy(&packet[1], remain, remain_pos);
+ /* Fixed header ends */
+
+ /* Variable header starts */
+ /* protocol length */
+ packet[remain_pos + 1] = 0x00;
+ packet[remain_pos + 2] = 0x04;
+ /* protocol name */
+ packet[remain_pos + 3] = 'M';
+ packet[remain_pos + 4] = 'Q';
+ packet[remain_pos + 5] = 'T';
+ packet[remain_pos + 6] = 'T';
+ /* protocol level */
+ packet[remain_pos + 7] = 0x04;
+ /* CONNECT flag: CleanSession */
+ packet[remain_pos + 8] = 0x02;
+ /* keep-alive 0 = disabled */
+ packet[remain_pos + 9] = 0x00;
+ packet[remain_pos + 10] = 0x3c;
+ /*end of variable header*/
+ return remain_pos + 10;
+}
+
static CURLcode mqtt_connect(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
- const size_t client_id_offset = 14;
- const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
+ int pos = 0;
+ int rc = 0;
+ /*remain length*/
+ int remain_pos = 0;
+ char remain[4] = {0};
+ size_t packetlen = 0;
+ size_t payloadlen = 0;
+ size_t start_user = 0;
+ size_t start_pwd = 0;
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
const size_t clen = strlen("curl");
- char packet[32] = {
- MQTT_MSG_CONNECT, /* packet type */
- 0x00, /* remaining length */
- 0x00, 0x04, /* protocol length */
- 'M','Q','T','T', /* protocol name */
- 0x04, /* protocol level */
- 0x02, /* CONNECT flag: CleanSession */
- 0x00, 0x3c, /* keep-alive 0 = disabled */
- 0x00, 0x00 /* payload1 length */
- };
- packet[1] = (packetlen - 2) & 0x7f;
- packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;
+ char *packet = NULL;
+
+ /* extracting username from request */
+ const char *username = data->state.aptr.user ?
+ data->state.aptr.user : "";
+ const size_t ulen = strlen(username);
+ /* extracting password from request */
+ const char *passwd = data->state.aptr.passwd ?
+ data->state.aptr.passwd : "";
+ const size_t plen = strlen(passwd);
+
+ payloadlen = ulen + plen + MQTT_CLIENTID_LEN + 2;
+ /* The plus 2 are for the MSB and LSB describing the length of the string to
+ * be added on the payload. Refer to spec 1.5.2 and 1.5.4 */
+ if(ulen)
+ payloadlen += 2;
+ if(plen)
+ payloadlen += 2;
+
+ /* getting how much occupy the remain length */
+ remain_pos = mqtt_encode_len(remain, payloadlen + 10);
+
+ /* 10 length of variable header and 1 the first byte of the fixed header */
+ packetlen = payloadlen + 10 + remain_pos + 1;
+
+ /* allocating packet */
+ if(packetlen > 268435455)
+ return CURLE_WEIRD_SERVER_REPLY;
+ packet = malloc(packetlen);
+ if(!packet)
+ return CURLE_OUT_OF_MEMORY;
+ memset(packet, 0, packetlen);
+
+ /* set initial values for CONN pack */
+ pos = init_connpack(packet, remain, remain_pos);
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
MQTT_CLIENTID_LEN - clen + 1);
- memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
- infof(data, "Using client id '%s'\n", client_id);
+ /* add client id */
+ rc = add_client_id(client_id, strlen(client_id), packet, pos + 1);
+ if(rc) {
+ failf(data, "Client ID length mismatched: [%lu]", strlen(client_id));
+ result = CURLE_WEIRD_SERVER_REPLY;
+ goto end;
+ }
+ infof(data, "Using client id '%s'", client_id);
+
+ /* position where starts the user payload */
+ start_user = pos + 3 + MQTT_CLIENTID_LEN;
+ /* position where starts the password payload */
+ start_pwd = start_user + ulen;
+ /* if user name was provided, add it to the packet */
+ if(ulen) {
+ start_pwd += 2;
+
+ rc = add_user(username, ulen,
+ (unsigned char *)packet, start_user, remain_pos);
+ if(rc) {
+ failf(data, "Username is too large: [%lu]", ulen);
+ result = CURLE_WEIRD_SERVER_REPLY;
+ goto end;
+ }
+ }
+
+ /* if passwd was provided, add it to the packet */
+ if(plen) {
+ rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos);
+ if(rc) {
+ failf(data, "Password is too large: [%lu]", plen);
+ result = CURLE_WEIRD_SERVER_REPLY;
+ goto end;
+ }
+ }
+
if(!result)
result = mqtt_send(data, packet, packetlen);
+
+end:
+ if(packet)
+ free(packet);
+ Curl_safefree(data->state.aptr.user);
+ Curl_safefree(data->state.aptr.passwd);
return result;
}
@@ -213,35 +382,12 @@ fail:
static CURLcode mqtt_get_topic(struct Curl_easy *data,
char **topic, size_t *topiclen)
{
- CURLcode result = CURLE_OK;
char *path = data->state.up.path;
-
- if(strlen(path) > 1) {
- result = Curl_urldecode(data, path + 1, 0, topic, topiclen,
- REJECT_NADA);
- }
- else {
- failf(data, "Error: No topic specified.");
- result = CURLE_URL_MALFORMAT;
- }
- return result;
-}
-
-
-static int mqtt_encode_len(char *buf, size_t len)
-{
- unsigned char encoded;
- int i;
-
- for(i = 0; (len > 0) && (i<4); i++) {
- encoded = len % 0x80;
- len /= 0x80;
- if(len)
- encoded |= 0x80;
- buf[i] = encoded;
- }
-
- return i;
+ if(strlen(path) > 1)
+ return Curl_urldecode(data, path + 1, 0, topic, topiclen,
+ REJECT_NADA);
+ failf(data, "No MQTT topic found. Forgot to URL encode it?");
+ return CURLE_URL_MALFORMAT;
}
static CURLcode mqtt_subscribe(struct Curl_easy *data)
@@ -418,7 +564,7 @@ static void mqstate(struct Curl_easy *data,
struct connectdata *conn = data->conn;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
#ifdef CURLDEBUG
- infof(data, "%s (from %s) (next is %s)\n",
+ infof(data, "%s (from %s) (next is %s)",
statenames[state],
statenames[mqtt->state],
(state == MQTT_FIRST)? statenames[nextstate] : "");
@@ -465,7 +611,7 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
goto MQTT_SUBACK_COMING;
}
else if(packet == MQTT_MSG_DISCONNECT) {
- infof(data, "Got DISCONNECT\n");
+ infof(data, "Got DISCONNECT");
*done = TRUE;
goto end;
}
@@ -476,7 +622,13 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
/* -- switched state -- */
remlen = mq->remaining_length;
- infof(data, "Remaining length: %zd bytes\n", remlen);
+ infof(data, "Remaining length: %zd bytes", remlen);
+ if(data->set.max_filesize &&
+ (curl_off_t)remlen > data->set.max_filesize) {
+ failf(data, "Maximum file size exceeded");
+ result = CURLE_FILESIZE_EXCEEDED;
+ goto end;
+ }
Curl_pgrsSetDownloadSize(data, remlen);
data->req.bytecount = 0;
data->req.size = remlen;
@@ -491,12 +643,12 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
if(result) {
if(CURLE_AGAIN == result) {
- infof(data, "EEEE AAAAGAIN\n");
+ infof(data, "EEEE AAAAGAIN");
}
goto end;
}
if(!nread) {
- infof(data, "server disconnected\n");
+ infof(data, "server disconnected");
result = CURLE_PARTIAL_FILE;
goto end;
}
@@ -562,7 +714,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
return result;
}
- infof(data, "mqtt_doing: state [%d]\n", (int) mqtt->state);
+ infof(data, "mqtt_doing: state [%d]", (int) mqtt->state);
switch(mqtt->state) {
case MQTT_FIRST:
/* Read the initial byte only */
@@ -582,6 +734,10 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
pkt[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4));
+ if(nread && (byte & 0x80))
+ /* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 +
+ 127 * 128^3 bytes. server tried to send more */
+ result = CURLE_WEIRD_SERVER_REPLY;
if(result)
break;
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
@@ -593,7 +749,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
mqstate(data, MQTT_FIRST, MQTT_FIRST);
if(mq->firstbyte == MQTT_MSG_DISCONNECT) {
- infof(data, "Got DISCONNECT\n");
+ infof(data, "Got DISCONNECT");
*done = TRUE;
}
break;
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 1b3e261c6..518ceb51f 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -169,7 +169,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state
connection_id = data->conn->connection_id;
infof(data,
- "STATE: %s => %s handle %p; line %d (connection #%ld)\n",
+ "STATE: %s => %s handle %p; line %d (connection #%ld)",
statename[oldstate], statename[data->mstate],
(void *)data, lineno, connection_id);
}
@@ -562,7 +562,7 @@ static CURLcode multi_done(struct Curl_easy *data,
struct connectdata *conn = data->conn;
unsigned int i;
- DEBUGF(infof(data, "multi_done\n"));
+ DEBUGF(infof(data, "multi_done"));
if(data->state.done)
/* Stop if multi_done() has already been called */
@@ -610,7 +610,7 @@ static CURLcode multi_done(struct Curl_easy *data,
/* Stop if still used. */
CONNCACHE_UNLOCK(data);
DEBUGF(infof(data, "Connection still in use %zu, "
- "no more multi_done now!\n",
+ "no more multi_done now!",
conn->easyq.size));
return CURLE_OK;
}
@@ -687,7 +687,7 @@ static CURLcode multi_done(struct Curl_easy *data,
if(Curl_conncache_return_conn(data, conn)) {
/* remember the most recently used connection */
data->state.lastconnect_id = conn->connection_id;
- infof(data, "%s\n", buffer);
+ infof(data, "%s", buffer);
}
else
data->state.lastconnect_id = -1;
@@ -709,7 +709,6 @@ static int close_connect_only(struct Curl_easy *data,
return 1;
connclose(conn, "Removing connect-only easy handle");
- conn->bits.connect_only = FALSE;
return 1;
}
@@ -1043,16 +1042,27 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
data = multi->easyp;
while(data) {
- int bitmap = multi_getsock(data, sockbunch);
+ int bitmap;
+#ifdef __clang_analyzer_
+ /* to prevent "The left operand of '>=' is a garbage value" warnings */
+ memset(sockbunch, 0, sizeof(sockbunch));
+#endif
+ bitmap = multi_getsock(data, sockbunch);
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
curl_socket_t s = CURL_SOCKET_BAD;
- if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
+ if(!FDSET_SOCK(sockbunch[i]))
+ /* pretend it doesn't exist */
+ continue;
FD_SET(sockbunch[i], read_fd_set);
s = sockbunch[i];
}
- if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
+ if(!FDSET_SOCK(sockbunch[i]))
+ /* pretend it doesn't exist */
+ continue;
FD_SET(sockbunch[i], write_fd_set);
s = sockbunch[i];
}
@@ -1096,6 +1106,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
WSANETWORKEVENTS wsa_events;
DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
#endif
+#ifndef ENABLE_WAKEUP
+ (void)use_wakeup;
+#endif
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -1176,7 +1189,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
#ifdef USE_WINSOCK
long mask = 0;
#endif
- if(bitmap & GETSOCK_READSOCK(i)) {
+ if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
s = sockbunch[i];
#ifdef USE_WINSOCK
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
@@ -1185,7 +1198,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
ufds[nfds].events = POLLIN;
++nfds;
}
- if(bitmap & GETSOCK_WRITESOCK(i)) {
+ if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
s = sockbunch[i];
#ifdef USE_WINSOCK
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
@@ -1540,6 +1553,58 @@ static CURLcode multi_do_more(struct Curl_easy *data, int *complete)
}
/*
+ * Check whether a timeout occurred, and handle it if it did
+ */
+static bool multi_handle_timeout(struct Curl_easy *data,
+ struct curltime *now,
+ bool *stream_error,
+ CURLcode *result,
+ bool connect_timeout)
+{
+ timediff_t timeout_ms;
+ timeout_ms = Curl_timeleft(data, now, connect_timeout);
+
+ if(timeout_ms < 0) {
+ /* Handle timed out */
+ if(data->mstate == MSTATE_RESOLVING)
+ failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
+ " milliseconds",
+ Curl_timediff(*now, data->progress.t_startsingle));
+ else if(data->mstate == MSTATE_CONNECTING)
+ failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
+ " milliseconds",
+ Curl_timediff(*now, data->progress.t_startsingle));
+ else {
+ struct SingleRequest *k = &data->req;
+ if(k->size != -1) {
+ failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+ " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
+ CURL_FORMAT_CURL_OFF_T " bytes received",
+ Curl_timediff(*now, data->progress.t_startsingle),
+ k->bytecount, k->size);
+ }
+ else {
+ failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
+ " milliseconds with %" CURL_FORMAT_CURL_OFF_T
+ " bytes received",
+ Curl_timediff(*now, data->progress.t_startsingle),
+ k->bytecount);
+ }
+ }
+
+ /* Force connection closed if the connection has indeed been used */
+ if(data->mstate > MSTATE_DO) {
+ streamclose(data->conn, "Disconnected with pending data");
+ *stream_error = TRUE;
+ }
+ *result = CURLE_OPERATION_TIMEDOUT;
+ (void)multi_done(data, *result, TRUE);
+ }
+
+ return (timeout_ms < 0);
+}
+
+/*
* We are doing protocol-specific connecting and this is being called over and
* over from the multi interface until the connection phase is done on
* protocol layer.
@@ -1670,7 +1735,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
bool done = FALSE;
CURLMcode rc;
CURLcode result = CURLE_OK;
- timediff_t timeout_ms;
timediff_t recv_timeout_ms;
timediff_t send_timeout_ms;
int control;
@@ -1685,7 +1749,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
rc = CURLM_OK;
if(multi_ischanged(multi, TRUE)) {
- DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
+ DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!"));
process_pending_handles(multi); /* multiplexed */
}
@@ -1700,47 +1764,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->conn &&
(data->mstate >= MSTATE_CONNECT) &&
(data->mstate < MSTATE_COMPLETED)) {
+ /* Check for overall operation timeout here but defer handling the
+ * connection timeout to later, to allow for a connection to be set up
+ * in the window since we last checked timeout. This prevents us
+ * tearing down a completed connection in the case where we were slow
+ * to check the timeout (e.g. process descheduled during this loop).
+ * We set connect_timeout=FALSE to do this. */
+
/* we need to wait for the connect state as only then is the start time
stored, but we must not check already completed handles */
- timeout_ms = Curl_timeleft(data, nowp,
- (data->mstate <= MSTATE_DO)?
- TRUE:FALSE);
-
- if(timeout_ms < 0) {
- /* Handle timed out */
- if(data->mstate == MSTATE_RESOLVING)
- failf(data, "Resolving timed out after %" CURL_FORMAT_TIMEDIFF_T
- " milliseconds",
- Curl_timediff(*nowp, data->progress.t_startsingle));
- else if(data->mstate == MSTATE_CONNECTING)
- failf(data, "Connection timed out after %" CURL_FORMAT_TIMEDIFF_T
- " milliseconds",
- Curl_timediff(*nowp, data->progress.t_startsingle));
- else {
- struct SingleRequest *k = &data->req;
- if(k->size != -1) {
- failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
- " milliseconds with %" CURL_FORMAT_CURL_OFF_T " out of %"
- CURL_FORMAT_CURL_OFF_T " bytes received",
- Curl_timediff(*nowp, data->progress.t_startsingle),
- k->bytecount, k->size);
- }
- else {
- failf(data, "Operation timed out after %" CURL_FORMAT_TIMEDIFF_T
- " milliseconds with %" CURL_FORMAT_CURL_OFF_T
- " bytes received",
- Curl_timediff(*nowp, data->progress.t_startsingle),
- k->bytecount);
- }
- }
-
- /* Force connection closed if the connection has indeed been used */
- if(data->mstate > MSTATE_DO) {
- streamclose(data->conn, "Disconnected with pending data");
- stream_error = TRUE;
- }
- result = CURLE_OPERATION_TIMEDOUT;
- (void)multi_done(data, result, TRUE);
+ if(multi_handle_timeout(data, nowp, &stream_error, &result, FALSE)) {
/* Skip the statemachine and go directly to error handling section. */
goto statemachine_end;
}
@@ -1792,7 +1825,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else if(data->state.previouslypending) {
/* this transfer comes from the pending queue so try move another */
- infof(data, "Transfer was pending, now try another\n");
+ infof(data, "Transfer was pending, now try another");
process_pending_handles(data->multi);
}
@@ -1847,7 +1880,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->state.async.done = TRUE;
#endif
result = CURLE_OK;
- infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
+ infof(data, "Hostname '%s' was found in DNS cache", hostname);
}
if(!dns)
@@ -2279,7 +2312,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLcode ret = Curl_retry_request(data, &newurl);
if(!ret) {
- infof(data, "Downgrades to HTTP/1.1!\n");
+ infof(data, "Downgrades to HTTP/1.1!");
streamclose(data->conn, "Disconnect HTTP/2 for HTTP/1");
data->state.httpwant = CURL_HTTP_VERSION_1_1;
/* clear the error message bit too as we ignore the one we got */
@@ -2418,6 +2451,21 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
default:
return CURLM_INTERNAL_ERROR;
}
+
+ if(data->conn &&
+ data->mstate >= MSTATE_CONNECT &&
+ data->mstate < MSTATE_DO &&
+ rc != CURLM_CALL_MULTI_PERFORM &&
+ !multi_ischanged(multi, false)) {
+ /* We now handle stream timeouts if and only if this will be the last
+ * loop iteration. We only check this on the last iteration to ensure
+ * that if we know we have additional work to do immediately
+ * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before
+ * declaring the connection timed out as we may almost have a completed
+ * connection. */
+ multi_handle_timeout(data, nowp, &stream_error, &result, TRUE);
+ }
+
statemachine_end:
if(data->mstate < MSTATE_COMPLETED) {
@@ -3339,7 +3387,7 @@ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id)
rc = Curl_splayremove(multi->timetree, &data->state.timenode,
&multi->timetree);
if(rc)
- infof(data, "Internal error removing splay node = %d\n", rc);
+ infof(data, "Internal error removing splay node = %d", rc);
}
/* Indicate that we are in the splay tree and insert the new timer expiry
@@ -3386,7 +3434,7 @@ void Curl_expire_clear(struct Curl_easy *data)
rc = Curl_splayremove(multi->timetree, &data->state.timenode,
&multi->timetree);
if(rc)
- infof(data, "Internal error clearing splay node = %d\n", rc);
+ infof(data, "Internal error clearing splay node = %d", rc);
/* flush the timeout list too */
while(list->size > 0) {
@@ -3394,7 +3442,7 @@ void Curl_expire_clear(struct Curl_easy *data)
}
#ifdef DEBUGBUILD
- infof(data, "Expire cleared (transfer %p)\n", data);
+ infof(data, "Expire cleared (transfer %p)", data);
#endif
nowp->tv_sec = 0;
nowp->tv_usec = 0;
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index 96b84749f..2e4a6ffba 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -153,6 +153,9 @@ struct Curl_multi {
bool recheckstate; /* see Curl_multi_connchanged */
bool in_callback; /* true while executing a callback */
bool ipv6_works;
+#ifdef USE_OPENSSL
+ bool ssl_seeded;
+#endif
};
#endif /* HEADER_CURL_MULTIHANDLE_H */
diff --git a/Utilities/cmcurl/lib/netrc.c b/Utilities/cmcurl/lib/netrc.c
index 13610bb07..0a4ae2cdc 100644
--- a/Utilities/cmcurl/lib/netrc.c
+++ b/Utilities/cmcurl/lib/netrc.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,8 @@
enum host_lookup_state {
NOTHING,
HOSTFOUND, /* the 'machine' keyword was found */
- HOSTVALID /* this is "our" machine! */
+ HOSTVALID, /* this is "our" machine! */
+ MACDEF
};
#define NETRC_FILE_MISSING 1
@@ -84,12 +85,17 @@ static int parsenetrc(const char *host,
int netrcbuffsize = (int)sizeof(netrcbuffer);
while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
+ if(state == MACDEF) {
+ if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
+ state = NOTHING;
+ else
+ continue;
+ }
tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
if(tok && *tok == '#')
/* treat an initial hash as a comment line */
continue;
while(tok) {
-
if((login && *login) && (password && *password)) {
done = TRUE;
break;
@@ -97,7 +103,13 @@ static int parsenetrc(const char *host,
switch(state) {
case NOTHING:
- if(strcasecompare("machine", tok)) {
+ if(strcasecompare("macdef", tok)) {
+ /* Define a macro. A macro is defined with the specified name; its
+ contents begin with the next .netrc line and continue until a
+ null line (consecutive new-line characters) is encountered. */
+ state = MACDEF;
+ }
+ else if(strcasecompare("machine", tok)) {
/* the next tok is the machine name, this is in itself the
delimiter that starts the stuff entered for this machine,
after this we need to search for 'login' and
@@ -109,6 +121,11 @@ static int parsenetrc(const char *host,
retcode = NETRC_SUCCESS; /* we did find our host */
}
break;
+ case MACDEF:
+ if(!strlen(tok)) {
+ state = NOTHING;
+ }
+ break;
case HOSTFOUND:
if(strcasecompare(host, tok)) {
/* and yes, this is our host! */
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index 932cf89ee..3b77ae98d 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -31,6 +31,7 @@
#include "sendf.h"
#include "urldata.h"
#include "multiif.h"
+#include "strerror.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -104,6 +105,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
iconv_t *cd = &tmpcd;
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
+ char ebuffer[STRERROR_LEN];
/* open an iconv conversion descriptor if necessary */
if(data)
@@ -116,7 +118,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_NETWORK,
CURL_ICONV_CODESET_OF_HOST,
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
}
@@ -130,7 +132,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"The Curl_convert_to_network iconv call failed with errno %i: %s",
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
#else
@@ -170,6 +172,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
iconv_t *cd = &tmpcd;
char *input_ptr, *output_ptr;
size_t in_bytes, out_bytes, rc;
+ char ebuffer[STRERROR_LEN];
/* open an iconv conversion descriptor if necessary */
if(data)
@@ -182,7 +185,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_OF_NETWORK,
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
}
@@ -196,7 +199,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"Curl_convert_from_network iconv call failed with errno %i: %s",
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
#else
@@ -237,6 +240,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
char *input_ptr;
char *output_ptr;
size_t in_bytes, out_bytes, rc;
+ char ebuffer[STRERROR_LEN];
/* open an iconv conversion descriptor if necessary */
if(data)
@@ -249,7 +253,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
"The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
CURL_ICONV_CODESET_OF_HOST,
CURL_ICONV_CODESET_FOR_UTF8,
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
}
@@ -263,7 +267,7 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
if((rc == ICONV_ERROR) || (in_bytes)) {
failf(data,
"The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
- errno, strerror(errno));
+ errno, Curl_strerror(errno, ebuffer, sizeof(ebuffer)));
return CURLE_CONV_FAILED;
}
if(output_ptr < input_ptr) {
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index 0b8bc34a0..fb5e743c2 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -247,7 +247,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
#ifdef USE_SSL
if(conn->handler->flags & PROTOPT_SSL) {
CURLcode result;
- result = Curl_ssl_connect_nonblocking(data, conn,
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &li->ssldone);
if(result)
return result;
@@ -270,7 +270,8 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
if(conn->handler->flags & PROTOPT_SSL) {
/* Is the SSL handshake complete yet? */
if(!li->ssldone) {
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
+ FIRSTSOCKET,
&li->ssldone);
if(result || !li->ssldone)
return result;
@@ -399,7 +400,7 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
connkeep(conn, "OpenLDAP do");
- infof(data, "LDAP local: %s\n", data->state.url);
+ infof(data, "LDAP local: %s", data->state.url);
rc = ldap_url_parse(data->state.url, &ludp);
if(rc != LDAP_URL_SUCCESS) {
@@ -509,7 +510,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
else {
/* successful */
if(code == LDAP_SIZELIMIT_EXCEEDED)
- infof(data, "There are more than %d entries\n", lr->nument);
+ infof(data, "There are more than %d entries", lr->nument);
data->req.size = data->req.bytecount;
*err = CURLE_OK;
ret = 0;
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index 481173995..84c7f51de 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -402,7 +402,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
clipamount = gotbytes - i;
restart = TRUE;
DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
- "server response left\n",
+ "server response left",
(int)clipamount));
}
else if(keepon) {
@@ -412,7 +412,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
with it. We keep the first bytes of the line then we throw
away the rest. */
infof(data, "Excessive server response line length received, "
- "%zd bytes. Stripping\n", gotbytes);
+ "%zd bytes. Stripping", gotbytes);
restart = TRUE;
/* we keep 40 bytes since all our pingpong protocols are only
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 9b6ea6480..d3f3de6d4 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -75,7 +75,6 @@
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
-#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
@@ -308,7 +307,7 @@ static void state(struct Curl_easy *data, pop3state newstate)
};
if(pop3c->state != newstate)
- infof(data, "POP3 %p state change from %s to %s\n",
+ infof(data, "POP3 %p state change from %s to %s",
(void *)pop3c, names[pop3c->state], names[newstate]);
#endif
@@ -370,8 +369,9 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
{
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
- &pop3c->ssldone);
+ CURLcode result =
+ Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET,
+ &pop3c->ssldone);
if(!result) {
if(pop3c->state != POP3_UPGRADETLS)
@@ -551,7 +551,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
result = pop3_perform_user(data, conn);
else {
/* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!");
result = CURLE_LOGIN_DENIED;
}
}
@@ -740,28 +740,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
}
}
}
- else if(pop3code == '+') {
- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
- /* We don't have a SSL/TLS connection yet, but SSL is requested */
- if(pop3c->tls_supported)
- /* Switch to TLS connection now */
- result = pop3_perform_starttls(data, conn);
- else if(data->set.use_ssl == CURLUSESSL_TRY)
- /* Fallback and carry on with authentication */
- result = pop3_perform_authentication(data, conn);
- else {
- failf(data, "STLS not supported.");
- result = CURLE_USE_SSL_FAILED;
- }
- }
- else
- result = pop3_perform_authentication(data, conn);
- }
else {
/* Clear text is supported when CAPA isn't recognised */
- pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
+ if(pop3code != '+')
+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
- result = pop3_perform_authentication(data, conn);
+ if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
+ result = pop3_perform_authentication(data, conn);
+ else if(pop3code == '+' && pop3c->tls_supported)
+ /* Switch to TLS connection now */
+ result = pop3_perform_starttls(data, conn);
+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
+ /* Fallback and carry on with authentication */
+ result = pop3_perform_authentication(data, conn);
+ else {
+ failf(data, "STLS not supported.");
+ result = CURLE_USE_SSL_FAILED;
+ }
}
return result;
@@ -776,6 +771,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.pop3c.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(pop3code != '+') {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied");
@@ -1031,7 +1030,7 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn,
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &pop3c->ssldone);
if(result || !pop3c->ssldone)
return result;
@@ -1172,7 +1171,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
@@ -1191,7 +1190,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
return result;
}
@@ -1274,11 +1273,11 @@ static CURLcode pop3_doing(struct Curl_easy *data, bool *dophase_done)
CURLcode result = pop3_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
result = pop3_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index 4bcd615eb..f5ef6bd52 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -377,7 +377,12 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */
{
if(us < 1)
return size * 1000000;
- return (curl_off_t)((long double)size/us * 1000000);
+ else if(size < CURL_OFF_T_MAX/1000000)
+ return (size * 1000000) / us;
+ else if(us >= 1000000)
+ return size / (us / 1000000);
+ else
+ return CURL_OFF_T_MAX;
}
/* returns TRUE if it's time to show the progress meter */
diff --git a/Utilities/cmcurl/lib/quic.h b/Utilities/cmcurl/lib/quic.h
index 947f13edc..b030359dd 100644
--- a/Utilities/cmcurl/lib/quic.h
+++ b/Utilities/cmcurl/lib/quic.h
@@ -45,7 +45,7 @@ CURLcode Curl_quic_is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
bool *connected);
-int Curl_quic_ver(char *p, size_t len);
+void Curl_quic_ver(char *p, size_t len);
CURLcode Curl_quic_done_sending(struct Curl_easy *data);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index 951fedb0a..8f2c1ba29 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
if(!seeded) {
struct curltime now = Curl_now();
- infof(data, "WARNING: Using weak random seed\n");
+ infof(data, "WARNING: Using weak random seed");
randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
randseed = randseed * 1103515245 + 12345;
randseed = randseed * 1103515245 + 12345;
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 007d5c50b..30fefb9b8 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -231,7 +231,7 @@ static CURLcode rtsp_done(struct Curl_easy *data,
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
(data->conn->proto.rtspc.rtp_channel == -1)) {
- infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
+ infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv);
}
}
@@ -651,7 +651,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
/* We have the full RTP interleaved packet
* Write out the header including the leading '$' */
- DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
+ DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
rtspc->rtp_channel, rtp_length));
result = rtp_client_write(data, &rtp[0], rtp_length + 4);
if(result) {
@@ -682,7 +682,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
if(rtp_dataleft && rtp[0] == '$') {
- DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
+ DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
*readmore ? "(READMORE)" : ""));
/* Store the incomplete RTP packet for a "rewind" */
diff --git a/Utilities/cmcurl/lib/rtsp.h b/Utilities/cmcurl/lib/rtsp.h
index 1e9cb7d2c..da11ade04 100644
--- a/Utilities/cmcurl/lib/rtsp.h
+++ b/Utilities/cmcurl/lib/rtsp.h
@@ -22,7 +22,7 @@
*
***************************************************************************/
#ifdef USE_HYPER
-#define CURL_DISABLE_RTSP
+#define CURL_DISABLE_RTSP 1
#endif
#ifndef CURL_DISABLE_RTSP
diff --git a/Utilities/cmcurl/lib/select.h b/Utilities/cmcurl/lib/select.h
index 4db64877b..59a571dbb 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -97,8 +97,10 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
#if defined(TPF)
#define VALID_SOCK(x) 1
#define VERIFY_SOCK(x) Curl_nop_stmt
+#define FDSET_SOCK(x) 1
#elif defined(USE_WINSOCK)
#define VALID_SOCK(s) ((s) < INVALID_SOCKET)
+#define FDSET_SOCK(x) 1
#define VERIFY_SOCK(x) do { \
if(!VALID_SOCK(x)) { \
SET_SOCKERRNO(WSAEINVAL); \
@@ -106,13 +108,17 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
} \
} while(0)
#else
-#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
-#define VERIFY_SOCK(x) do { \
- if(!VALID_SOCK(x)) { \
- SET_SOCKERRNO(EINVAL); \
- return -1; \
- } \
-} while(0)
+#define VALID_SOCK(s) ((s) >= 0)
+
+/* If the socket is small enough to get set or read from an fdset */
+#define FDSET_SOCK(s) ((s) < FD_SETSIZE)
+
+#define VERIFY_SOCK(x) do { \
+ if(!VALID_SOCK(x) || !FDSET_SOCK(x)) { \
+ SET_SOCKERRNO(EINVAL); \
+ return -1; \
+ } \
+ } while(0)
#endif
#endif /* HEADER_CURL_SELECT_H */
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index e41bb805f..14ca84bfe 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -236,29 +236,21 @@ bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
/* Curl_infof() is for info message along the way */
+#define MAXINFO 2048
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
+ DEBUGASSERT(!strchr(fmt, '\n'));
if(data && data->set.verbose) {
va_list ap;
size_t len;
- char print_buffer[2048 + 1];
+ char buffer[MAXINFO + 2];
va_start(ap, fmt);
- len = mvsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
- /*
- * Indicate truncation of the input by replacing the last 3 characters
- * with "...", and transfer the newline over in case the format had one.
- */
- if(len >= sizeof(print_buffer)) {
- len = strlen(fmt);
- if(fmt[--len] == '\n')
- msnprintf(print_buffer + (sizeof(print_buffer) - 5), 5, "...\n");
- else
- msnprintf(print_buffer + (sizeof(print_buffer) - 4), 4, "...");
- }
+ len = mvsnprintf(buffer, MAXINFO, fmt, ap);
va_end(ap);
- len = strlen(print_buffer);
- Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
+ buffer[len++] = '\n';
+ buffer[len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, buffer, len);
}
}
@@ -274,14 +266,14 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
size_t len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
- len = strlen(error);
+ len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
if(data->set.errorbuffer && !data->state.errorbuf) {
strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
error[len++] = '\n';
+ error[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, error, len);
va_end(ap);
}
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index fb8b86d47..08827d1ef 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -1689,7 +1689,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSLCERT_BLOB:
/*
- * Blob that holds file name of the SSL certificate to use
+ * Blob that holds file content of the SSL certificate to use
*/
result = Curl_setblobopt(&data->set.blobs[BLOB_CERT],
va_arg(param, struct curl_blob *));
@@ -1704,7 +1704,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_PROXY_SSLCERT_BLOB:
/*
- * Blob that holds file name of the SSL certificate to use for proxy
+ * Blob that holds file content of the SSL certificate to use for proxy
*/
result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY],
va_arg(param, struct curl_blob *));
@@ -1735,7 +1735,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSLKEY_BLOB:
/*
- * Blob that holds file name of the SSL key to use
+ * Blob that holds file content of the SSL key to use
*/
result = Curl_setblobopt(&data->set.blobs[BLOB_KEY],
va_arg(param, struct curl_blob *));
@@ -1750,7 +1750,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_PROXY_SSLKEY_BLOB:
/*
- * Blob that holds file name of the SSL key to use for proxy
+ * Blob that holds file content of the SSL key to use for proxy
*/
result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY],
va_arg(param, struct curl_blob *));
@@ -1872,7 +1872,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_DOH_SSL_VERIFYPEER:
/*
- * Enable peer SSL verifying for DOH.
+ * Enable peer SSL verifying for DoH.
*/
data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
TRUE : FALSE;
@@ -1911,7 +1911,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_DOH_SSL_VERIFYHOST:
/*
- * Enable verification of the host name in the peer certificate for DOH
+ * Enable verification of the host name in the peer certificate for DoH
*/
arg = va_arg(param, long);
@@ -1955,7 +1955,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_DOH_SSL_VERIFYSTATUS:
/*
- * Enable certificate status verifying for DOH.
+ * Enable certificate status verifying for DoH.
*/
if(!Curl_ssl_cert_status_request()) {
result = CURLE_NOT_BUILT_IN;
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index c34f97e8f..a2e7e4131 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -42,8 +42,9 @@
#ifdef USE_MBEDTLS
#include <mbedtls/version.h>
-#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
- #define HAS_RESULT_CODE_BASED_FUNCTIONS
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000) && \
+ (MBEDTLS_VERSION_NUMBER < 0x03000000)
+ #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
#endif
#endif /* USE_MBEDTLS */
@@ -105,8 +106,8 @@ typedef mbedtls_sha256_context SHA256_CTX;
static void SHA256_Init(SHA256_CTX *ctx)
{
-#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_sha256_starts(ctx, 0);
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+ (void) mbedtls_sha256_starts(ctx, 0);
#else
(void) mbedtls_sha256_starts_ret(ctx, 0);
#endif
@@ -116,8 +117,8 @@ static void SHA256_Update(SHA256_CTX *ctx,
const unsigned char *data,
unsigned int length)
{
-#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_sha256_update(ctx, data, length);
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+ (void) mbedtls_sha256_update(ctx, data, length);
#else
(void) mbedtls_sha256_update_ret(ctx, data, length);
#endif
@@ -125,8 +126,8 @@ static void SHA256_Update(SHA256_CTX *ctx,
static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
{
-#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
- mbedtls_sha256_finish(ctx, digest);
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+ (void) mbedtls_sha256_finish(ctx, digest);
#else
(void) mbedtls_sha256_finish_ret(ctx, digest);
#endif
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 39facb267..fd49cf6aa 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -204,7 +204,7 @@ static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
};
if(smbc->state != newstate)
- infof(data, "SMB conn %p state change from %s to %s\n",
+ infof(data, "SMB conn %p state change from %s to %s",
(void *)smbc, names[smbc->state], names[newstate]);
#endif
@@ -230,7 +230,7 @@ static void request_state(struct Curl_easy *data,
};
if(req->state != newstate)
- infof(data, "SMB request %p state change from %s to %s\n",
+ infof(data, "SMB request %p state change from %s to %s",
(void *)req, names[req->state], names[newstate]);
#endif
@@ -670,7 +670,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
#ifdef USE_SSL
if((conn->handler->flags & PROTOPT_SSL)) {
bool ssl_done = FALSE;
- result = Curl_ssl_connect_nonblocking(data, conn,
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &ssl_done);
if(result && result != CURLE_AGAIN)
return result;
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index feffc05bc..02ddaca0a 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -78,7 +78,6 @@
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
-#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
@@ -308,7 +307,7 @@ static void state(struct Curl_easy *data, smtpstate newstate)
};
if(smtpc->state != newstate)
- infof(data, "SMTP %p state change from %s to %s\n",
+ infof(data, "SMTP %p state change from %s to %s",
(void *)smtpc, names[smtpc->state], names[newstate]);
#endif
@@ -397,7 +396,8 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
/* Start the SSL connection */
struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FIRSTSOCKET,
+ CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
+ FIRSTSOCKET,
&smtpc->ssldone);
if(!result) {
@@ -484,7 +484,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
state(data, SMTP_AUTH);
else {
/* Other mechanisms not supported */
- infof(data, "No known authentication mechanisms supported!\n");
+ infof(data, "No known authentication mechanisms supported!");
result = CURLE_LOGIN_DENIED;
}
}
@@ -834,6 +834,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)instate; /* no use for this yet */
+ /* Pipelining in response is forbidden. */
+ if(data->conn->proto.smtpc.pp.cache_size)
+ return CURLE_WEIRD_SERVER_REPLY;
+
if(smtpcode != 220) {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied, code %d", smtpcode);
@@ -1258,7 +1262,7 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
struct smtp_conn *smtpc = &conn->proto.smtpc;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
- result = Curl_ssl_connect_nonblocking(data, conn,
+ result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &smtpc->ssldone);
if(result || !smtpc->ssldone)
return result;
@@ -1455,7 +1459,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
struct connectdata *conn = data->conn;
struct SMTP *smtp = data->req.p.smtp;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
/* Requested no body means no transfer */
@@ -1495,7 +1499,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done)
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
return result;
}
@@ -1579,11 +1583,11 @@ static CURLcode smtp_doing(struct Curl_easy *data, bool *dophase_done)
CURLcode result = smtp_multi_statemach(data, dophase_done);
if(result)
- DEBUGF(infof(data, "DO phase failed\n"));
+ DEBUGF(infof(data, "DO phase failed"));
else if(*dophase_done) {
result = smtp_dophase_done(data, FALSE /* not connected */);
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
diff --git a/Utilities/cmcurl/lib/socketpair.c b/Utilities/cmcurl/lib/socketpair.c
index 2c580ad2d..409d2ad66 100644
--- a/Utilities/cmcurl/lib/socketpair.c
+++ b/Utilities/cmcurl/lib/socketpair.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2019 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,6 +48,10 @@
#endif /* !INADDR_LOOPBACK */
#endif /* !WIN32 */
+#include "nonblock.h" /* for curlx_nonblock */
+#include "timeval.h" /* needed before select.h */
+#include "select.h" /* for Curl_poll */
+
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -59,12 +63,11 @@ int Curl_socketpair(int domain, int type, int protocol,
union {
struct sockaddr_in inaddr;
struct sockaddr addr;
- } a;
+ } a, a2;
curl_socket_t listener;
curl_socklen_t addrlen = sizeof(a.inaddr);
int reuse = 1;
- char data[2][12];
- ssize_t dlen;
+ struct pollfd pfd[1];
(void)domain;
(void)type;
(void)protocol;
@@ -85,7 +88,8 @@ int Curl_socketpair(int domain, int type, int protocol,
goto error;
if(bind(listener, &a.addr, sizeof(a.inaddr)) == -1)
goto error;
- if(getsockname(listener, &a.addr, &addrlen) == -1)
+ if(getsockname(listener, &a.addr, &addrlen) == -1 ||
+ addrlen < (int)sizeof(a.inaddr))
goto error;
if(listen(listener, 1) == -1)
goto error;
@@ -94,18 +98,30 @@ int Curl_socketpair(int domain, int type, int protocol,
goto error;
if(connect(socks[0], &a.addr, sizeof(a.inaddr)) == -1)
goto error;
+
+ /* use non-blocking accept to make sure we don't block forever */
+ if(curlx_nonblock(listener, TRUE) < 0)
+ goto error;
+ pfd[0].fd = listener;
+ pfd[0].events = POLLIN;
+ pfd[0].revents = 0;
+ (void)Curl_poll(pfd, 1, 10*1000); /* 10 seconds */
socks[1] = accept(listener, NULL, NULL);
if(socks[1] == CURL_SOCKET_BAD)
goto error;
/* verify that nothing else connected */
- msnprintf(data[0], sizeof(data[0]), "%p", socks);
- dlen = strlen(data[0]);
- if(swrite(socks[0], data[0], dlen) != dlen)
+ addrlen = sizeof(a.inaddr);
+ if(getsockname(socks[0], &a.addr, &addrlen) == -1 ||
+ addrlen < (int)sizeof(a.inaddr))
goto error;
- if(sread(socks[1], data[1], sizeof(data[1])) != dlen)
+ addrlen = sizeof(a2.inaddr);
+ if(getpeername(socks[1], &a2.addr, &addrlen) == -1 ||
+ addrlen < (int)sizeof(a2.inaddr))
goto error;
- if(memcmp(data[0], data[1], dlen))
+ if(a.inaddr.sin_family != a2.inaddr.sin_family ||
+ a.inaddr.sin_addr.s_addr != a2.inaddr.sin_addr.s_addr ||
+ a.inaddr.sin_port != a2.inaddr.sin_port)
goto error;
sclose(listener);
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 5cde4a46a..db4c80834 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -99,24 +99,24 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */
}
#endif
-#ifndef DEBUGBUILD
-#define sxstate(x,y) socksstate(x,y)
-#else
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#define DEBUG_AND_VERBOSE
#define sxstate(x,y) socksstate(x,y, __LINE__)
+#else
+#define sxstate(x,y) socksstate(x,y)
#endif
-
/* always use this function to change state, to make debugging easier */
static void socksstate(struct Curl_easy *data,
enum connect_t state
-#ifdef DEBUGBUILD
+#ifdef DEBUG_AND_VERBOSE
, int lineno
#endif
)
{
struct connectdata *conn = data->conn;
enum connect_t oldstate = conn->cnnct.state;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#ifdef DEBUG_AND_VERBOSE
/* synced with the state list in urldata.h */
static const char * const statename[] = {
"INIT",
@@ -146,9 +146,9 @@ static void socksstate(struct Curl_easy *data,
conn->cnnct.state = state;
-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#ifdef DEBUG_AND_VERBOSE
infof(data,
- "SXSTATE: %s => %s conn %p; line %d\n",
+ "SXSTATE: %s => %s conn %p; line %d",
statename[oldstate], statename[conn->cnnct.state], conn,
lineno);
#endif
@@ -214,10 +214,10 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* SOCKS4 can only do IPv4, insist! */
conn->ip_version = CURL_IPRESOLVE_V4;
if(conn->bits.httpproxy)
- infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d",
protocol4a ? "a" : "", hostname, remote_port);
- infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
+ infof(data, "SOCKS4 communication to %s:%d", hostname, remote_port);
/*
* Compose socks4 request
@@ -244,7 +244,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
return CURLPX_RESOLVE_HOST;
else if(rc == CURLRESOLV_PENDING) {
sxstate(data, CONNECT_RESOLVING);
- infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
+ infof(data, "SOCKS4 non-blocking resolve of %s", hostname);
return CURLPX_OK;
}
sxstate(data, CONNECT_RESOLVED);
@@ -264,7 +264,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
- infof(data, "Hostname '%s' was found\n", hostname);
+ infof(data, "Hostname '%s' was found", hostname);
sxstate(data, CONNECT_RESOLVED);
}
else {
@@ -279,18 +279,21 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
struct Curl_addrinfo *hp = NULL;
- char buf[64];
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
* returns a Curl_addrinfo pointer that may not always look the same.
*/
- if(dns)
+ if(dns) {
hp = dns->addr;
- if(hp) {
- Curl_printable_address(hp, buf, sizeof(buf));
- if(hp->ai_family == AF_INET) {
+ /* scan for the first IPv4 address */
+ while(hp && (hp->ai_family != AF_INET))
+ hp = hp->ai_next;
+
+ if(hp) {
struct sockaddr_in *saddr_in;
+ char buf[64];
+ Curl_printable_address(hp, buf, sizeof(buf));
saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
@@ -298,20 +301,19 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];
- infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
- }
- else {
- hp = NULL; /* fail! */
- failf(data, "SOCKS4 connection to %s not supported", buf);
- }
+ infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)", buf);
- Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+ Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+ }
+ else
+ failf(data, "SOCKS4 connection to %s not supported", hostname);
}
- if(!hp) {
+ else
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
hostname);
+
+ if(!hp)
return CURLPX_RESOLVE_HOST;
- }
}
/* FALLTHROUGH */
CONNECT_REQ_INIT:
@@ -435,7 +437,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* Result */
switch(socksreq[1]) {
case 90:
- infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
+ infof(data, "SOCKS4%s request granted.", protocol4a?"a":"");
break;
case 91:
failf(data,
@@ -528,19 +530,19 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
switch(sx->state) {
case CONNECT_SOCKS_INIT:
if(conn->bits.httpproxy)
- infof(data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+ infof(data, "SOCKS5: connecting to HTTP proxy %s port %d",
hostname, remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
infof(data, "SOCKS5: server resolving disabled for hostnames of "
- "length > 255 [actual len=%zu]\n", hostname_len);
+ "length > 255 [actual len=%zu]", hostname_len);
socks5_resolve_local = TRUE;
}
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
infof(data,
- "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
+ "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu",
auth);
if(!(auth & CURLAUTH_BASIC))
/* disable username/password auth */
@@ -778,7 +780,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
- infof(data, "SOCKS5: hostname '%s' found\n", hostname);
+ infof(data, "SOCKS5: hostname '%s' found", hostname);
}
if(!dns) {
@@ -820,7 +822,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest);
+ infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)", dest);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
@@ -834,7 +836,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
+ infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)", dest);
}
#endif
else {
@@ -858,7 +860,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
socksreq[len++] = (char) hostname_len; /* one byte address length */
memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
len += hostname_len;
- infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n",
+ infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
hostname, remote_port);
}
/* FALLTHROUGH */
@@ -1022,7 +1024,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
}
sxstate(data, CONNECT_DONE);
}
- infof(data, "SOCKS5 request granted.\n");
+ infof(data, "SOCKS5 request granted.");
*done = TRUE;
return CURLPX_OK; /* Proxy was successful! */
diff --git a/Utilities/cmcurl/lib/socks_gssapi.c b/Utilities/cmcurl/lib/socks_gssapi.c
index 10b942a98..34bfa37d7 100644
--- a/Utilities/cmcurl/lib/socks_gssapi.c
+++ b/Utilities/cmcurl/lib/socks_gssapi.c
@@ -328,7 +328,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
user[gss_send_token.length] = '\0';
gss_release_name(&gss_status, &gss_client_name);
gss_release_buffer(&gss_status, &gss_send_token);
- infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n",user);
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.",user);
free(user);
user = NULL;
@@ -344,7 +344,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
else if(gss_ret_flags & GSS_C_INTEG_FLAG)
gss_enc = 1;
- infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.",
(gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
/* force for the moment to no data protection */
gss_enc = 0;
@@ -518,7 +518,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
(void)curlx_nonblock(sock, TRUE);
- infof(data, "SOCKS5 access with%s protection granted.\n",
+ infof(data, "SOCKS5 access with%s protection granted.",
(socksreq[0] == 0)?"out GSS-API data":
((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
diff --git a/Utilities/cmcurl/lib/socks_sspi.c b/Utilities/cmcurl/lib/socks_sspi.c
index 813c6be57..cb225b9b5 100644
--- a/Utilities/cmcurl/lib/socks_sspi.c
+++ b/Utilities/cmcurl/lib/socks_sspi.c
@@ -327,7 +327,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
failf(data, "Failed to determine user name.");
return CURLE_COULDNT_CONNECT;
}
- infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n",
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
names.sUserName);
s_pSecFn->FreeContextBuffer(names.sUserName);
@@ -343,7 +343,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
gss_enc = 1;
- infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
+ infof(data, "SOCKS5 server supports GSS-API %s data protection.",
(gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") );
/* force to no data protection, avoid encryption/decryption for now */
gss_enc = 0;
@@ -591,7 +591,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
}
(void)curlx_nonblock(sock, TRUE);
- infof(data, "SOCKS5 access with%s protection granted.\n",
+ infof(data, "SOCKS5 access with%s protection granted.",
(socksreq[0] == 0)?"out GSS-API data":
((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c
index 9af47ea47..85cf33b3e 100644
--- a/Utilities/cmcurl/lib/strdup.c
+++ b/Utilities/cmcurl/lib/strdup.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,6 +24,10 @@
#include <curl/curl.h>
+#ifdef WIN32
+#include <wchar.h>
+#endif
+
#include "strdup.h"
#include "curl_memory.h"
@@ -50,6 +54,28 @@ char *curlx_strdup(const char *str)
}
#endif
+#ifdef WIN32
+/***************************************************************************
+ *
+ * Curl_wcsdup(source)
+ *
+ * Copies the 'source' wchar string to a newly allocated buffer (that is
+ * returned).
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+wchar_t *Curl_wcsdup(const wchar_t *src)
+{
+ size_t length = wcslen(src);
+
+ if(length > (SIZE_T_MAX / sizeof(wchar_t)) - 1)
+ return (wchar_t *)NULL; /* integer overflow */
+
+ return (wchar_t *)Curl_memdup(src, (length + 1) * sizeof(wchar_t));
+}
+#endif
+
/***************************************************************************
*
* Curl_memdup(source, length)
diff --git a/Utilities/cmcurl/lib/strdup.h b/Utilities/cmcurl/lib/strdup.h
index 0936956f8..8c8a6f20e 100644
--- a/Utilities/cmcurl/lib/strdup.h
+++ b/Utilities/cmcurl/lib/strdup.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,9 @@
#ifndef HAVE_STRDUP
extern char *curlx_strdup(const char *str);
#endif
+#ifdef WIN32
+wchar_t* Curl_wcsdup(const wchar_t* src);
+#endif
void *Curl_memdup(const void *src, size_t buffer_length);
void *Curl_saferealloc(void *ptr, size_t size);
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 5298a0d76..8a2719765 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -188,8 +188,8 @@ curl_easy_strerror(CURLcode error)
case CURLE_UNKNOWN_OPTION:
return "An unknown option was passed in to libcurl";
- case CURLE_TELNET_OPTION_SYNTAX :
- return "Malformed telnet option";
+ case CURLE_SETOPT_OPTION_SYNTAX :
+ return "Malformed option provided in a setopt";
case CURLE_GOT_NOTHING:
return "Server returned nothing (no headers, no data)";
@@ -735,7 +735,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
#if defined(WIN32)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
- strncpy(buf, strerror(err), max);
+ strncpy(buf, sys_errlist[err], max);
else
#endif
{
@@ -786,6 +786,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
}
#else
{
+ /* !checksrc! disable STRERROR 1 */
const char *msg = strerror(err);
if(msg)
strncpy(buf, msg, max);
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index fdd137fb0..a81bb81c3 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -268,9 +268,9 @@ static void printoption(struct Curl_easy *data,
if(data->set.verbose) {
if(cmd == CURL_IAC) {
if(CURL_TELCMD_OK(option))
- infof(data, "%s IAC %s\n", direction, CURL_TELCMD(option));
+ infof(data, "%s IAC %s", direction, CURL_TELCMD(option));
else
- infof(data, "%s IAC %d\n", direction, option);
+ infof(data, "%s IAC %d", direction, option);
}
else {
const char *fmt = (cmd == CURL_WILL) ? "WILL" :
@@ -287,12 +287,12 @@ static void printoption(struct Curl_easy *data,
opt = NULL;
if(opt)
- infof(data, "%s %s %s\n", direction, fmt, opt);
+ infof(data, "%s %s %s", direction, fmt, opt);
else
- infof(data, "%s %s %d\n", direction, fmt, option);
+ infof(data, "%s %s %d", direction, fmt, option);
}
else
- infof(data, "%s %d %d\n", direction, cmd, option);
+ infof(data, "%s %d %d", direction, cmd, option);
}
}
}
@@ -765,8 +765,6 @@ static void printsub(struct Curl_easy *data,
break;
}
}
- if(direction)
- infof(data, "\n");
}
}
@@ -834,7 +832,7 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
else {
failf(data, "Syntax error in telnet option: %s", head->data);
- result = CURLE_TELNET_OPTION_SYNTAX;
+ result = CURLE_SETOPT_OPTION_SYNTAX;
break;
}
continue;
@@ -855,7 +853,7 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
break;
}
failf(data, "Syntax error in telnet option: %s", head->data);
- result = CURLE_TELNET_OPTION_SYNTAX;
+ result = CURLE_SETOPT_OPTION_SYNTAX;
break;
}
@@ -922,12 +920,17 @@ static void suboption(struct Curl_easy *data)
size_t tmplen = (strlen(v->data) + 1);
/* Add the variable only if it fits */
if(len + tmplen < (int)sizeof(temp)-6) {
- if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
- msnprintf((char *)&temp[len], sizeof(temp) - len,
- "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
- CURL_NEW_ENV_VALUE, varval);
- len += tmplen;
- }
+ int rv;
+ char sep[2] = "";
+ varval[0] = 0;
+ rv = sscanf(v->data, "%127[^,]%1[,]%127s", varname, sep, varval);
+ if(rv == 1)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s", CURL_NEW_ENV_VAR, varname);
+ else if(rv >= 2)
+ len += msnprintf((char *)&temp[len], sizeof(temp) - len,
+ "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+ CURL_NEW_ENV_VALUE, varval);
}
}
msnprintf((char *)&temp[len], sizeof(temp) - len,
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 11150af36..aae997d0f 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -239,7 +239,7 @@ static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
infof(state->data,
"set timeouts for state %d; Total % " CURL_FORMAT_CURL_OFF_T
- ", retry %d maxtry %d\n",
+ ", retry %d maxtry %d",
(int)state->state, timeout_ms, state->retry_time, state->retry_max);
/* init RX time */
@@ -325,7 +325,7 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
return CURLE_TFTP_ILLEGAL;
}
- infof(data, "got option=(%s) value=(%s)\n", option, value);
+ infof(data, "got option=(%s) value=(%s)", option, value);
if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
long blksize;
@@ -356,14 +356,14 @@ static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
}
state->blksize = (int)blksize;
- infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
+ infof(data, "%s (%d) %s (%d)", "blksize parsed from OACK",
state->blksize, "requested", state->requested_blksize);
}
else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
long tsize = 0;
tsize = strtol(value, NULL, 10);
- infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize);
+ infof(data, "%s (%ld)", "tsize parsed from OACK", tsize);
/* tsize should be ignored on upload: Who cares about the size of the
remote file? */
@@ -397,7 +397,7 @@ static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
struct Curl_easy *data = state->data;
- infof(data, "%s\n", "Connected for transmit");
+ infof(data, "%s", "Connected for transmit");
#endif
state->state = TFTP_STATE_TX;
result = tftp_set_timeouts(state);
@@ -413,7 +413,7 @@ static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
struct Curl_easy *data = state->data;
- infof(data, "%s\n", "Connected for receive");
+ infof(data, "%s", "Connected for receive");
#endif
state->state = TFTP_STATE_RX;
result = tftp_set_timeouts(state);
@@ -596,12 +596,12 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
else if(state->block == rblock) {
/* This is the last recently received block again. Log it and ACK it
again. */
- infof(data, "Received last DATA packet block %d again.\n", rblock);
+ infof(data, "Received last DATA packet block %d again.", rblock);
}
else {
/* totally unexpected, just log it */
infof(data,
- "Received unexpected DATA packet block %d, expecting block %d\n",
+ "Received unexpected DATA packet block %d, expecting block %d",
rblock, NEXT_BLOCKNUM(state->block));
break;
}
@@ -653,7 +653,7 @@ static CURLcode tftp_rx(struct tftp_state_data *state,
/* Increment the retry count and fail if over the limit */
state->retries++;
infof(data,
- "Timeout waiting for block %d ACK. Retries = %d\n",
+ "Timeout waiting for block %d ACK. Retries = %d",
NEXT_BLOCKNUM(state->block), state->retries);
if(state->retries > state->retry_max) {
state->error = TFTP_ERR_TIMEOUT;
@@ -720,11 +720,11 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
/* There's a bug in tftpd-hpa that causes it to send us an ack for
* 65535 when the block number wraps to 0. So when we're expecting
* 0, also accept 65535. See
- * http://syslinux.zytor.com/archives/2010-September/015253.html
+ * https://www.syslinux.org/archives/2010-September/015612.html
* */
!(state->block == 0 && rblock == 65535)) {
/* This isn't the expected block. Log it and up the retry counter */
- infof(data, "Received ACK for block %d, expecting %d\n",
+ infof(data, "Received ACK for block %d, expecting %d",
rblock, state->block);
state->retries++;
/* Bail out if over the maximum */
@@ -797,7 +797,7 @@ static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
/* Increment the retry counter and log the timeout */
state->retries++;
infof(data, "Timeout waiting for block %d ACK. "
- " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
+ " Retries = %d", NEXT_BLOCKNUM(state->block), state->retries);
/* Decide if we've had enough */
if(state->retries > state->retry_max) {
state->error = TFTP_ERR_TIMEOUT;
@@ -906,22 +906,22 @@ static CURLcode tftp_state_machine(struct tftp_state_data *state,
switch(state->state) {
case TFTP_STATE_START:
- DEBUGF(infof(data, "TFTP_STATE_START\n"));
+ DEBUGF(infof(data, "TFTP_STATE_START"));
result = tftp_send_first(state, event);
break;
case TFTP_STATE_RX:
- DEBUGF(infof(data, "TFTP_STATE_RX\n"));
+ DEBUGF(infof(data, "TFTP_STATE_RX"));
result = tftp_rx(state, event);
break;
case TFTP_STATE_TX:
- DEBUGF(infof(data, "TFTP_STATE_TX\n"));
+ DEBUGF(infof(data, "TFTP_STATE_TX"));
result = tftp_tx(state, event);
break;
case TFTP_STATE_FIN:
- infof(data, "%s\n", "TFTP finished");
+ infof(data, "%s", "TFTP finished");
break;
default:
- DEBUGF(infof(data, "STATE: %d\n", state->state));
+ DEBUGF(infof(data, "STATE: %d", state->state));
failf(data, "%s", "Internal state machine error");
result = CURLE_TFTP_ILLEGAL;
break;
@@ -1153,7 +1153,7 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
size_t strn = state->rbytes - 4;
state->error = (tftp_error_t)error;
if(tftp_strnlen(str, strn) < strn)
- infof(data, "TFTP error: %s\n", str);
+ infof(data, "TFTP error: %s", str);
break;
}
case TFTP_EVENT_ACK:
@@ -1288,7 +1288,7 @@ static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done)
result = tftp_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
else if(!result) {
/* The multi code doesn't have this logic for the DOING state so we
@@ -1325,7 +1325,7 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done)
tftp_multi_statemach(data, dophase_done);
if(*dophase_done)
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
return result;
}
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index bca4e548f..05fec7998 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -188,7 +188,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
/* at this point we already verified that the callback exists
so we compile and store the trailers buffer, then proceed */
infof(data,
- "Moving trailers state machine from initialized to sending.\n");
+ "Moving trailers state machine from initialized to sending.");
data->state.trailers_state = TRAILERS_SENDING;
Curl_dyn_init(&data->state.trailers_buf, DYN_TRAILERS);
@@ -211,7 +211,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
curl_slist_free_all(trailers);
return result;
}
- infof(data, "Successfully compiled trailers.\r\n");
+ infof(data, "Successfully compiled trailers.");
curl_slist_free_all(trailers);
}
#endif
@@ -376,7 +376,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
data->set.trailer_callback = NULL;
/* mark the transfer as done */
data->req.upload_done = TRUE;
- infof(data, "Signaling end of chunked upload after trailers.\n");
+ infof(data, "Signaling end of chunked upload after trailers.");
}
else
#endif
@@ -385,7 +385,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
/* mark this as done once this chunk is transferred */
data->req.upload_done = TRUE;
infof(data,
- "Signaling end of chunked upload via terminating chunk.\n");
+ "Signaling end of chunked upload via terminating chunk.");
}
if(added_crlf)
@@ -463,7 +463,7 @@ CURLcode Curl_readrewind(struct Curl_easy *data)
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
data->set.ioctl_client);
Curl_set_in_callback(data, false);
- infof(data, "the ioctl callback returned %d\n", (int)err);
+ infof(data, "the ioctl callback returned %d", (int)err);
if(err) {
failf(data, "ioctl callback returned error %d", (int)err);
@@ -530,7 +530,7 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
default:
if(timeofdoc <= data->set.timevalue) {
infof(data,
- "The requested document is not new enough\n");
+ "The requested document is not new enough");
data->info.timecond = TRUE;
return FALSE;
}
@@ -538,7 +538,7 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
case CURL_TIMECOND_IFUNMODSINCE:
if(timeofdoc >= data->set.timevalue) {
infof(data,
- "The requested document is not old enough\n");
+ "The requested document is not old enough");
data->info.timecond = TRUE;
return FALSE;
}
@@ -615,7 +615,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
else {
/* read nothing but since we wanted nothing we consider this an OK
situation to proceed from */
- DEBUGF(infof(data, "readwrite_data: we're done!\n"));
+ DEBUGF(infof(data, "readwrite_data: we're done!"));
nread = 0;
}
@@ -638,10 +638,10 @@ static CURLcode readwrite_data(struct Curl_easy *data,
server closed the connection and we bail out from this! */
#ifdef USE_NGHTTP2
if(is_http2 && !nread)
- DEBUGF(infof(data, "nread == 0, stream closed, bailing\n"));
+ DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
else
#endif
- DEBUGF(infof(data, "nread <= 0, server closed connection, bailing\n"));
+ DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
k->keepon &= ~KEEP_RECV;
break;
}
@@ -684,7 +684,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
infof(data,
"Excess found:"
" excess = %zd"
- " url = %s (zero-length body)\n",
+ " url = %s (zero-length body)",
nread, data->state.up.path);
}
@@ -764,7 +764,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
written to the client. */
if(conn->chunk.datasize) {
infof(data, "Leftovers after chunking: % "
- CURL_FORMAT_CURL_OFF_T "u bytes\n",
+ CURL_FORMAT_CURL_OFF_T "u bytes",
conn->chunk.datasize);
}
}
@@ -775,7 +775,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Account for body content stored in the header buffer */
if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
size_t headlen = Curl_dyn_len(&data->state.headerb);
- DEBUGF(infof(data, "Increasing bytecount by %zu\n", headlen));
+ DEBUGF(infof(data, "Increasing bytecount by %zu", headlen));
k->bytecount += headlen;
}
@@ -789,7 +789,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
" excess = %zu"
", size = %" CURL_FORMAT_CURL_OFF_T
", maxdownload = %" CURL_FORMAT_CURL_OFF_T
- ", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
excess, k->size, k->maxdownload, k->bytecount);
connclose(conn, "excess found in a read");
}
@@ -898,7 +898,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* When we've read the entire thing and the close bit is set, the server
may now close the connection. If there's now any kind of sending going
on from our side, we need to stop that immediately. */
- infof(data, "we are done reading and this is set to close, stop send\n");
+ infof(data, "we are done reading and this is set to close, stop send");
k->keepon &= ~KEEP_SEND; /* no writing anymore either */
}
@@ -923,7 +923,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data,
return CURLE_OK;
}
-#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#if defined(WIN32) && defined(USE_WINSOCK)
#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
#endif
@@ -1128,7 +1128,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
(k->writebytecount == data->state.infilesize)) {
/* we have sent all data we were supposed to */
k->upload_done = TRUE;
- infof(data, "We are completely uploaded and fine\n");
+ infof(data, "We are completely uploaded and fine");
}
if(k->upload_present != bytes_written) {
@@ -1199,7 +1199,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(data->state.drain) {
select_res |= CURL_CSELECT_IN;
- DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data\n"));
+ DEBUGF(infof(data, "Curl_readwrite: forcibly told to drain data"));
}
if(!select_res) /* Call for select()/poll() only, if read/write/error
@@ -1212,8 +1212,12 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
#ifdef USE_HYPER
- if(conn->datastream)
- return conn->datastream(data, conn, &didwhat, done, select_res);
+ if(conn->datastream) {
+ result = conn->datastream(data, conn, &didwhat, done, select_res);
+ if(result || *done)
+ return result;
+ }
+ else {
#endif
/* We go ahead and do a read if we have a readable socket or if
the stream was rewound (in which case we have data in a
@@ -1232,6 +1236,9 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(result)
return result;
}
+#ifdef USE_HYPER
+ }
+#endif
k->now = Curl_now();
if(!didwhat) {
@@ -1256,7 +1263,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
- infof(data, "Done waiting for 100-continue\n");
+ infof(data, "Done waiting for 100-continue");
}
}
}
@@ -1496,7 +1503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
#endif
Curl_http2_init_state(&data->state);
- Curl_hsts_loadcb(data, data->hsts);
+ result = Curl_hsts_loadcb(data, data->hsts);
}
/*
@@ -1632,7 +1639,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
DEBUGASSERT(data->state.uh);
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
(type == FOLLOW_FAKE) ? CURLU_NON_SUPPORT_SCHEME :
- ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) );
+ ((type == FOLLOW_REDIR) ? CURLU_URLENCODE : 0) |
+ CURLU_ALLOW_SPACE);
if(uc) {
if(type != FOLLOW_FAKE)
return Curl_uc_to_curlcode(uc);
@@ -1671,7 +1679,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->state.url = newurl;
data->state.url_alloc = TRUE;
- infof(data, "Issue another request to this URL: '%s'\n", data->state.url);
+ infof(data, "Issue another request to this URL: '%s'", data->state.url);
/*
* We get here when the HTTP code is 300-399 (and 401). We need to perform
@@ -1714,7 +1722,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
|| data->state.httpreq == HTTPREQ_POST_FORM
|| data->state.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_301)) {
- infof(data, "Switch from POST to GET\n");
+ infof(data, "Switch from POST to GET");
data->state.httpreq = HTTPREQ_GET;
}
break;
@@ -1739,7 +1747,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
|| data->state.httpreq == HTTPREQ_POST_FORM
|| data->state.httpreq == HTTPREQ_POST_MIME)
&& !(data->set.keep_post & CURL_REDIR_POST_302)) {
- infof(data, "Switch from POST to GET\n");
+ infof(data, "Switch from POST to GET");
data->state.httpreq = HTTPREQ_GET;
}
break;
@@ -1757,7 +1765,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
!(data->set.keep_post & CURL_REDIR_POST_303))) {
data->state.httpreq = HTTPREQ_GET;
data->set.upload = false;
- infof(data, "Switch to %s\n",
+ infof(data, "Switch to %s",
data->set.opt_no_body?"HEAD":"GET");
}
break;
@@ -1818,7 +1826,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
to issue again, but the nghttp2 API can deliver the message to other
streams as well, which is why this adds the check the data counters
too. */
- infof(data, "REFUSED_STREAM, retrying a fresh connect\n");
+ infof(data, "REFUSED_STREAM, retrying a fresh connect");
data->state.refused_stream = FALSE; /* clear again */
retry = TRUE;
}
@@ -1830,8 +1838,8 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
data->state.retrycount = 0;
return CURLE_SEND_ERROR;
}
- infof(data, "Connection died, retrying a fresh connect\
-(retry count: %d)\n", data->state.retrycount);
+ infof(data, "Connection died, retrying a fresh connect (retry count: %d)",
+ data->state.retrycount);
*url = strdup(data->state.url);
if(!*url)
return CURLE_OUT_OF_MEMORY;
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 1ee38af0d..37b6c0e84 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -62,6 +62,14 @@
#ifdef USE_LIBIDN2
#include <idn2.h>
+#if defined(WIN32) && defined(UNICODE)
+#define IDN2_LOOKUP(name, host, flags) \
+ idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
+#else
+#define IDN2_LOOKUP(name, host, flags) \
+ idn2_lookup_ul((const char *)name, (char **)host, flags)
+#endif
+
#elif defined(USE_WIN32_IDN)
/* prototype for curl_win32_idn_to_ascii() */
bool curl_win32_idn_to_ascii(const char *in, char **out);
@@ -92,7 +100,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "speedcheck.h"
#include "warnless.h"
#include "non-ascii.h"
-#include "inet_pton.h"
#include "getinfo.h"
#include "urlapi-int.h"
#include "system_win32.h"
@@ -726,7 +733,16 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
{
DEBUGASSERT(conn);
DEBUGASSERT(data);
- infof(data, "Closing connection %ld\n", conn->connection_id);
+ infof(data, "Closing connection %ld", conn->connection_id);
+
+#ifndef USE_HYPER
+ if(conn->connect_state && conn->connect_state->prot_save) {
+ /* If this was closed with a CONNECT in progress, cleanup this temporary
+ struct arrangement */
+ data->req.p.http = NULL;
+ Curl_safefree(conn->connect_state->prot_save);
+ }
+#endif
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
@@ -824,7 +840,7 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
* are other users of it
*/
if(CONN_INUSE(conn) && !dead_connection) {
- DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
+ DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn)));
return CURLE_OK;
}
@@ -957,7 +973,7 @@ static bool conn_maxage(struct Curl_easy *data,
idletime /= 1000; /* integer seconds is fine */
if(idletime > data->set.maxage_conn) {
- infof(data, "Too old connection (%ld seconds), disconnect it\n",
+ infof(data, "Too old connection (%ld seconds), disconnect it",
idletime);
return TRUE;
}
@@ -1006,7 +1022,7 @@ static bool extract_if_dead(struct connectdata *conn,
}
if(dead) {
- infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
+ infof(data, "Connection %ld seems to be dead!", conn->connection_id);
Curl_conncache_remove_conn(data, conn, FALSE);
return TRUE;
}
@@ -1122,7 +1138,7 @@ ConnectionExists(struct Curl_easy *data,
/* Max pipe length is zero (unlimited) for multiplexed connections */
struct Curl_llist_element *curr;
- infof(data, "Found bundle for host %s: %p [%s]\n",
+ infof(data, "Found bundle for host %s: %p [%s]",
hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
"can multiplex" : "serially"));
@@ -1130,22 +1146,22 @@ ConnectionExists(struct Curl_easy *data,
if(canmultiplex) {
if(bundle->multiuse == BUNDLE_UNKNOWN) {
if(data->set.pipewait) {
- infof(data, "Server doesn't support multiplex yet, wait\n");
+ infof(data, "Server doesn't support multiplex yet, wait");
*waitpipe = TRUE;
CONNCACHE_UNLOCK(data);
return FALSE; /* no re-use */
}
- infof(data, "Server doesn't support multiplex (yet)\n");
+ infof(data, "Server doesn't support multiplex (yet)");
canmultiplex = FALSE;
}
if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
!Curl_multiplex_wanted(data->multi)) {
- infof(data, "Could multiplex, but not asked to!\n");
+ infof(data, "Could multiplex, but not asked to!");
canmultiplex = FALSE;
}
if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
- infof(data, "Can not multiplex, even if we wanted to!\n");
+ infof(data, "Can not multiplex, even if we wanted to!");
canmultiplex = FALSE;
}
}
@@ -1193,7 +1209,7 @@ ConnectionExists(struct Curl_easy *data,
completed yet and until then we don't re-use this connection */
if(!check->primary_ip[0]) {
infof(data,
- "Connection #%ld is still name resolving, can't reuse\n",
+ "Connection #%ld is still name resolving, can't reuse",
check->connection_id);
continue;
}
@@ -1202,7 +1218,7 @@ ConnectionExists(struct Curl_easy *data,
if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
foundPendingCandidate = TRUE;
/* Don't pick a connection that hasn't connected yet */
- infof(data, "Connection #%ld isn't open enough, can't reuse\n",
+ infof(data, "Connection #%ld isn't open enough, can't reuse",
check->connection_id);
continue;
}
@@ -1357,7 +1373,7 @@ ConnectionExists(struct Curl_easy *data,
&check->ssl_config)) {
DEBUGF(infof(data,
"Connection #%ld has different SSL parameters, "
- "can't reuse\n",
+ "can't reuse",
check->connection_id));
continue;
}
@@ -1365,7 +1381,7 @@ ConnectionExists(struct Curl_easy *data,
foundPendingCandidate = TRUE;
DEBUGF(infof(data,
"Connection #%ld has not started SSL connect, "
- "can't reuse\n",
+ "can't reuse",
check->connection_id));
continue;
}
@@ -1452,14 +1468,14 @@ ConnectionExists(struct Curl_easy *data,
/* Multiplexed connections can only be HTTP/2 for now */
struct http_conn *httpc = &check->proto.httpc;
if(multiplexed >= httpc->settings.max_concurrent_streams) {
- infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
+ infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
multiplexed);
continue;
}
else if(multiplexed >=
Curl_multi_max_concurrent_streams(data->multi)) {
infof(data, "client side MAX_CONCURRENT_STREAMS reached"
- ", skip (%zu)\n",
+ ", skip (%zu)",
multiplexed);
continue;
}
@@ -1467,7 +1483,7 @@ ConnectionExists(struct Curl_easy *data,
#endif
/* When not multiplexed, we have a match here! */
chosen = check;
- infof(data, "Multiplexed connection found!\n");
+ infof(data, "Multiplexed connection found!");
break;
}
else {
@@ -1490,7 +1506,7 @@ ConnectionExists(struct Curl_easy *data,
if(foundPendingCandidate && data->set.pipewait) {
infof(data,
- "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
+ "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set");
*waitpipe = TRUE;
}
@@ -1505,7 +1521,7 @@ void Curl_verboseconnect(struct Curl_easy *data,
struct connectdata *conn)
{
if(data->set.verbose)
- infof(data, "Connected to %s (%s) port %ld (#%ld)\n",
+ infof(data, "Connected to %s (%s) port %u (#%ld)",
#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
@@ -1577,12 +1593,12 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
#else
int flags = IDN2_NFC_INPUT;
#endif
- int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
+ int rc = IDN2_LOOKUP(host->name, &ace_hostname, flags);
if(rc != IDN2_OK)
/* fallback to TR46 Transitional mode for better IDNA2003
compatibility */
- rc = idn2_lookup_ul((const char *)host->name, &ace_hostname,
- IDN2_TRANSITIONAL);
+ rc = IDN2_LOOKUP(host->name, &ace_hostname,
+ IDN2_TRANSITIONAL);
if(rc == IDN2_OK) {
host->encalloc = (char *)ace_hostname;
/* change the name pointer to point to the encoded hostname */
@@ -1609,7 +1625,7 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
return CURLE_URL_MALFORMAT;
}
#else
- infof(data, "IDN support not present, can't parse Unicode domains\n");
+ infof(data, "IDN support not present, can't parse Unicode domains");
#endif
}
return CURLE_OK;
@@ -1876,9 +1892,13 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
#else
scopeidx = if_nametoindex(zoneid);
#endif
- if(!scopeidx)
- infof(data, "Invalid zoneid: %s; %s\n", zoneid,
- strerror(errno));
+ if(!scopeidx) {
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ char buffer[STRERROR_LEN];
+ infof(data, "Invalid zoneid: %s; %s", zoneid,
+ Curl_strerror(errno, buffer, sizeof(buffer)));
+#endif
+ }
else
conn->scope_id = scopeidx;
}
@@ -1934,7 +1954,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
CURLU_DISALLOW_USER : 0) |
(data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
if(uc) {
- DEBUGF(infof(data, "curl_url_set rejected %s\n", data->state.url));
+ DEBUGF(infof(data, "curl_url_set rejected %s", data->state.url));
return Curl_uc_to_curlcode(uc);
}
@@ -1979,7 +1999,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
}
data->state.url = url;
data->state.url_alloc = TRUE;
- infof(data, "Switched from HTTP to HTTPS due to HSTS => %s\n",
+ infof(data, "Switched from HTTP to HTTPS due to HSTS => %s",
data->state.url);
}
}
@@ -2333,7 +2353,7 @@ static char *detect_proxy(struct Curl_easy *data,
}
}
if(proxy)
- infof(data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
+ infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
return proxy;
}
@@ -2448,7 +2468,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
conn->bits.proxy_user_passwd = TRUE; /* enable it */
}
- curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
+ (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
if(portptr) {
port = (int)strtol(portptr, NULL, 10);
@@ -2576,7 +2596,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
no_proxy = curl_getenv(p);
}
if(no_proxy) {
- infof(data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ infof(data, "Uses proxy env variable %s == '%s'", p, no_proxy);
}
}
@@ -2871,11 +2891,13 @@ static CURLcode override_login(struct Curl_easy *data,
char **passwdp = &conn->passwd;
char **optionsp = &conn->options;
+#ifndef CURL_DISABLE_NETRC
if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
Curl_safefree(*userp);
Curl_safefree(*passwdp);
conn->bits.user_passwd = FALSE; /* disable user+password */
}
+#endif
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
@@ -2884,6 +2906,7 @@ static CURLcode override_login(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
+#ifndef CURL_DISABLE_NETRC
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
bool netrc_user_changed = FALSE;
@@ -2895,7 +2918,7 @@ static CURLcode override_login(struct Curl_easy *data,
&netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
- infof(data, "Couldn't find host %s in the %s file; using defaults\n",
+ infof(data, "Couldn't find host %s in the %s file; using defaults",
conn->host.name, data->set.str[STRING_NETRC_FILE]);
}
else if(ret < 0) {
@@ -2909,6 +2932,7 @@ static CURLcode override_login(struct Curl_easy *data,
conn->bits.user_passwd = TRUE; /* enable user+password */
}
}
+#endif
/* for updated strings, we update them in the URL */
if(*userp) {
@@ -2996,6 +3020,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
char *host_portno;
char *portptr;
int port = -1;
+ CURLcode result = CURLE_OK;
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void) data;
@@ -3025,7 +3050,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
if(*ptr == '%') {
/* There might be a zone identifier */
if(strncmp("%25", ptr, 3))
- infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
+ infof(data, "Please URL encode %% as %%25, see RFC 6874.");
ptr++;
/* Allow unreserved characters as defined in RFC 3986 */
while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
@@ -3036,7 +3061,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
/* yeps, it ended nicely with a bracket as well */
*ptr++ = '\0';
else
- infof(data, "Invalid IPv6 address format\n");
+ infof(data, "Invalid IPv6 address format");
portptr = ptr;
/* Note that if this didn't end with a bracket, we still advanced the
* hostptr first, but I can't see anything wrong with that as no host
@@ -3044,8 +3069,8 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
*/
#else
failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
- free(host_dup);
- return CURLE_NOT_BUILT_IN;
+ result = CURLE_NOT_BUILT_IN;
+ goto error;
#endif
}
@@ -3058,10 +3083,10 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
if(*host_portno) {
long portparse = strtol(host_portno, &endp, 10);
if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
- infof(data, "No valid port number in connect to host string (%s)\n",
+ failf(data, "No valid port number in connect to host string (%s)",
host_portno);
- hostptr = NULL;
- port = -1;
+ result = CURLE_SETOPT_OPTION_SYNTAX;
+ goto error;
}
else
port = (int)portparse; /* we know it will fit */
@@ -3072,15 +3097,16 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
if(hostptr) {
*hostname_result = strdup(hostptr);
if(!*hostname_result) {
- free(host_dup);
- return CURLE_OUT_OF_MEMORY;
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
}
}
*port_result = port;
+ error:
free(host_dup);
- return CURLE_OK;
+ return result;
}
/*
@@ -3176,7 +3202,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
conn->conn_to_host.name = host;
conn->bits.conn_to_host = TRUE;
- infof(data, "Connecting to hostname: %s\n", host);
+ infof(data, "Connecting to hostname: %s", host);
}
else {
/* no "connect to host" */
@@ -3187,7 +3213,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
if(port >= 0) {
conn->conn_to_port = port;
conn->bits.conn_to_port = TRUE;
- infof(data, "Connecting to port: %d\n", port);
+ infof(data, "Connecting to port: %d", port);
}
else {
/* no "connect to port" */
@@ -3248,7 +3274,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
conn->conn_to_port = as->dst.port;
conn->bits.conn_to_port = TRUE;
conn->bits.altused = TRUE;
- infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
+ infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d",
Curl_alpnid2str(srcalpnid), host, conn->remote_port,
Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
if(srcalpnid != as->dst.alpnid) {
@@ -3356,9 +3382,12 @@ static CURLcode resolve_server(struct Curl_easy *data,
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
- else if(rc == CURLRESOLV_TIMEDOUT)
+ else if(rc == CURLRESOLV_TIMEDOUT) {
+ failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
+ connhost->dispname,
+ Curl_timediff(Curl_now(), data->progress.t_startsingle));
result = CURLE_OPERATION_TIMEDOUT;
-
+ }
else if(!hostaddr) {
failf(data, "Could not resolve host: %s", connhost->dispname);
result = CURLE_COULDNT_RESOLVE_HOST;
@@ -3600,7 +3629,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result)
goto out;
- /* Check for overridden login details and set them accordingly so they
+ /* Check for overridden login details and set them accordingly so that
they are known when protocol->setup_connection is called! */
result = override_login(data, conn);
if(result)
@@ -3736,6 +3765,8 @@ static CURLcode create_conn(struct Curl_easy *data,
*/
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
@@ -3763,8 +3794,11 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
data->set.proxy_ssl.primary.ca_info_blob =
data->set.blobs[BLOB_CAINFO_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
- data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
@@ -3773,7 +3807,6 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
#endif
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
data->set.ssl.key = data->set.str[STRING_KEY];
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
@@ -3787,9 +3820,7 @@ static CURLcode create_conn(struct Curl_easy *data,
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
#endif
-
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
- data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
&conn->ssl_config)) {
@@ -3841,14 +3872,14 @@ static CURLcode create_conn(struct Curl_easy *data,
*in_connect = conn;
#ifndef CURL_DISABLE_PROXY
- infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
+ infof(data, "Re-using existing connection! (#%ld) with %s %s",
conn->connection_id,
conn->bits.proxy?"proxy":"host",
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
conn->host.dispname);
#else
- infof(data, "Re-using existing connection! (#%ld) with host %s\n",
+ infof(data, "Re-using existing connection! (#%ld) with host %s",
conn->connection_id, conn->host.dispname);
#endif
}
@@ -3888,7 +3919,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(conn_candidate)
(void)Curl_disconnect(data, conn_candidate, FALSE);
else {
- infof(data, "No more connections allowed to host %s: %zu\n",
+ infof(data, "No more connections allowed to host %s: %zu",
bundlehost, max_host_connections);
connections_available = FALSE;
}
@@ -3908,13 +3939,13 @@ static CURLcode create_conn(struct Curl_easy *data,
if(conn_candidate)
(void)Curl_disconnect(data, conn_candidate, FALSE);
else {
- infof(data, "No connections available in cache\n");
+ infof(data, "No connections available in cache");
connections_available = FALSE;
}
}
if(!connections_available) {
- infof(data, "No connections available.\n");
+ infof(data, "No connections available.");
conn_free(conn);
*in_connect = NULL;
@@ -3939,14 +3970,14 @@ static CURLcode create_conn(struct Curl_easy *data,
connection based. */
if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
data->state.authhost.done) {
- infof(data, "NTLM picked AND auth done set, clear picked!\n");
+ infof(data, "NTLM picked AND auth done set, clear picked!");
data->state.authhost.picked = CURLAUTH_NONE;
data->state.authhost.done = FALSE;
}
if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
data->state.authproxy.done) {
- infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
+ infof(data, "NTLM-proxy picked AND auth done set, clear picked!");
data->state.authproxy.picked = CURLAUTH_NONE;
data->state.authproxy.done = FALSE;
}
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index 6483208ec..7f03862cf 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -131,7 +131,7 @@ static const char *find_host_sep(const char *url)
*/
static bool urlchar_needs_escaping(int c)
{
- return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
+ return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
}
/*
@@ -580,7 +580,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname,
}
/* scan for byte values < 31 or 127 */
-static CURLUcode junkscan(const char *part)
+static bool junkscan(const char *part, unsigned int flags)
{
if(part) {
static const char badbytes[]={
@@ -588,17 +588,18 @@ static CURLUcode junkscan(const char *part)
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x7f,
- 0x00 /* null-terminate */
+ 0x7f, 0x00 /* null-terminate */
};
size_t n = strlen(part);
size_t nfine = strcspn(part, badbytes);
if(nfine != n)
/* since we don't know which part is scanned, return a generic error
code */
- return CURLUE_MALFORMED_INPUT;
+ return TRUE;
+ if(!(flags & CURLU_ALLOW_SPACE) && strchr(part, ' '))
+ return TRUE;
}
- return CURLUE_OK;
+ return FALSE;
}
static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
@@ -769,8 +770,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
size_t schemelen = 0;
size_t urllen;
- if(!url)
- return CURLUE_MALFORMED_INPUT;
+ DEBUGASSERT(url);
/*************************************************************
* Parse the URL.
@@ -884,9 +884,8 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
!(flags & CURLU_NON_SUPPORT_SCHEME))
return CURLUE_UNSUPPORTED_SCHEME;
- if(junkscan(schemep))
+ if(junkscan(schemep, flags))
return CURLUE_MALFORMED_INPUT;
-
}
else {
/* no scheme! */
@@ -927,7 +926,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
}
}
- if(junkscan(path))
+ if(junkscan(path, flags))
return CURLUE_MALFORMED_INPUT;
if((flags & CURLU_URLENCODE) && path[0]) {
@@ -991,7 +990,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
/*
* Parse the login details and strip them out of the host name.
*/
- if(junkscan(hostname))
+ if(junkscan(hostname, flags))
return CURLUE_MALFORMED_INPUT;
result = parse_hostname_login(u, &hostname, flags);
@@ -1155,7 +1154,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
const struct Curl_handler *h =
Curl_builtin_scheme(u->scheme);
if(h) {
- msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
}
}
@@ -1214,7 +1213,7 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
/* there's no stored port number, but asked to deliver
a default one for the scheme */
if(h) {
- msnprintf(portbuf, sizeof(portbuf), "%ld", h->defport);
+ msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
port = portbuf;
}
}
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index fb905c36c..6ffd97621 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -246,6 +246,7 @@ struct ssl_primary_config {
long version_max; /* max supported version the client wants to use*/
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
+ char *issuercert; /* optional issuer certificate filename */
char *clientcert;
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
@@ -254,6 +255,7 @@ struct ssl_primary_config {
char *pinned_key;
struct curl_blob *cert_blob;
struct curl_blob *ca_info_blob;
+ struct curl_blob *issuercert_blob;
char *curves; /* list of curves to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
@@ -265,8 +267,6 @@ struct ssl_config_data {
struct ssl_primary_config primary;
long certverifyresult; /* result from the certificate verification */
char *CRLfile; /* CRL to check certificate revocation */
- char *issuercert;/* optional issuer certificate filename */
- struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert_type; /* format for certificate (default: PEM)*/
@@ -508,7 +508,9 @@ struct ConnectBits {
BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */
BIT(ftp_use_control_ssl); /* Enabled SSL for the control connection */
#endif
+#ifndef CURL_DISABLE_NETRC
BIT(netrc); /* name+password provided by netrc */
+#endif
BIT(bound); /* set true if bind() has already been done on this socket/
connection */
BIT(multiplex); /* connection is multiplexed */
@@ -702,14 +704,15 @@ struct SingleRequest {
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
- BIT(header); /* incoming data has HTTP header */
+ BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
- BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
- upload and we're uploading the last chunk */
- BIT(ignorebody); /* we read a response-body but we ignore it! */
+ BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
+ upload and we're uploading the last chunk */
+ BIT(ignorebody); /* we read a response-body but we ignore it! */
BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
204 or 304 */
- BIT(chunk); /* if set, this is a chunked transfer-encoding */
+ BIT(chunk); /* if set, this is a chunked transfer-encoding */
+ BIT(ignore_cl); /* ignore content-length */
BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
on upload */
BIT(getheader); /* TRUE if header parsing is wanted */
@@ -1411,6 +1414,7 @@ struct UrlState {
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
#ifdef USE_HYPER
+ bool hconnect; /* set if a CONNECT request */
CURLcode hresult; /* used to pass return codes back from hyper callbacks */
#endif
@@ -1726,8 +1730,10 @@ struct UserDefined {
*/
curl_sshkeycallback ssh_keyfunc; /* key matching callback */
void *ssh_keyfunc_userp; /* custom pointer to callback */
+#ifndef CURL_DISABLE_NETRC
enum CURL_NETRC_OPTION
use_netrc; /* defined in include/curl.h */
+#endif
curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! */
long new_file_perms; /* Permissions to use when creating remote files */
@@ -1847,9 +1853,9 @@ struct UserDefined {
BIT(disallow_username_in_url); /* disallow username in url */
BIT(doh); /* DNS-over-HTTPS enabled */
BIT(doh_get); /* use GET for DoH requests, instead of POST */
- BIT(doh_verifypeer); /* DOH certificate peer verification */
- BIT(doh_verifyhost); /* DOH certificate hostname verification */
- BIT(doh_verifystatus); /* DOH certificate status verification */
+ BIT(doh_verifypeer); /* DoH certificate peer verification */
+ BIT(doh_verifyhost); /* DoH certificate hostname verification */
+ BIT(doh_verifystatus); /* DoH certificate status verification */
BIT(http09_allowed); /* allow HTTP/0.9 responses */
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
diff --git a/Utilities/cmcurl/lib/vauth/digest_sspi.c b/Utilities/cmcurl/lib/vauth/digest_sspi.c
index 2602ffd36..94f8f8c0d 100644
--- a/Utilities/cmcurl/lib/vauth/digest_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/digest_sspi.c
@@ -112,7 +112,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
/* Ensure we have a valid challenge message */
if(!Curl_bufref_len(chlg)) {
- infof(data, "DIGEST-MD5 handshake failure (empty challenge message)\n");
+ infof(data, "DIGEST-MD5 handshake failure (empty challenge message)");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -197,7 +197,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
+#endif
s_pSecFn->FreeCredentialsHandle(&credentials);
Curl_sspi_free_identity(p_identity);
@@ -207,7 +209,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
- infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ infof(data, "schannel: InitializeSecurityContext failed: %s",
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
return CURLE_AUTH_ERROR;
@@ -461,7 +463,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(status == SEC_E_OK)
output_token_len = chlg_buf[4].cbBuffer;
else { /* delete the context so a new one can be made */
- infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx\n",
+ infof(data, "digest_sspi: MakeSignature failed, error 0x%08lx",
(long)status);
s_pSecFn->DeleteSecurityContext(digest->http_context);
Curl_safefree(digest->http_context);
@@ -585,7 +587,9 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
status == SEC_I_COMPLETE_AND_CONTINUE)
s_pSecFn->CompleteAuthToken(&credentials, &resp_desc);
else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
+#endif
s_pSecFn->FreeCredentialsHandle(&credentials);
@@ -597,7 +601,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
- infof(data, "schannel: InitializeSecurityContext failed: %s\n",
+ infof(data, "schannel: InitializeSecurityContext failed: %s",
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
return CURLE_AUTH_ERROR;
diff --git a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
index b43982b9b..67d43bd56 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_gssapi.c
@@ -123,7 +123,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
if(chlg) {
if(!Curl_bufref_len(chlg)) {
- infof(data, "GSSAPI handshake failure (empty challenge message)\n");
+ infof(data, "GSSAPI handshake failure (empty challenge message)");
return CURLE_BAD_CONTENT_ENCODING;
}
input_token.value = (void *) Curl_bufref_ptr(chlg);
@@ -170,6 +170,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
* Parameters:
*
* data [in] - The session handle.
+ * authzid [in] - The authorization identity if some.
* chlg [in] - Optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
* out [out] - The result storage.
@@ -177,6 +178,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
+ const char *authzid,
const struct bufref *chlg,
struct kerberos5data *krb5,
struct bufref *out)
@@ -189,39 +191,17 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
OM_uint32 unused_status;
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
- unsigned int indata = 0;
- unsigned int outdata = 0;
+ unsigned char *indata;
gss_qop_t qop = GSS_C_QOP_DEFAULT;
unsigned int sec_layer = 0;
unsigned int max_size = 0;
- gss_name_t username = GSS_C_NO_NAME;
- gss_buffer_desc username_token;
/* Ensure we have a valid challenge message */
if(!Curl_bufref_len(chlg)) {
- infof(data, "GSSAPI handshake failure (empty security message)\n");
+ infof(data, "GSSAPI handshake failure (empty security message)");
return CURLE_BAD_CONTENT_ENCODING;
}
- /* Get the fully qualified username back from the context */
- major_status = gss_inquire_context(&minor_status, krb5->context,
- &username, NULL, NULL, NULL, NULL,
- NULL, NULL);
- if(GSS_ERROR(major_status)) {
- Curl_gss_log_error(data, "gss_inquire_context() failed: ",
- major_status, minor_status);
- return CURLE_AUTH_ERROR;
- }
-
- /* Convert the username from internal format to a displayable token */
- major_status = gss_display_name(&minor_status, username,
- &username_token, NULL);
- if(GSS_ERROR(major_status)) {
- Curl_gss_log_error(data, "gss_display_name() failed: ",
- major_status, minor_status);
- return CURLE_AUTH_ERROR;
- }
-
/* Setup the challenge "input" security buffer */
input_token.value = (void *) Curl_bufref_ptr(chlg);
input_token.length = Curl_bufref_len(chlg);
@@ -232,32 +212,32 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(GSS_ERROR(major_status)) {
Curl_gss_log_error(data, "gss_unwrap() failed: ",
major_status, minor_status);
- gss_release_buffer(&unused_status, &username_token);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Not 4 octets long so fail as per RFC4752 Section 3.1 */
if(output_token.length != 4) {
- infof(data, "GSSAPI handshake failure (invalid security data)\n");
- gss_release_buffer(&unused_status, &username_token);
+ infof(data, "GSSAPI handshake failure (invalid security data)");
return CURLE_BAD_CONTENT_ENCODING;
}
- /* Copy the data out and free the challenge as it is not required anymore */
- memcpy(&indata, output_token.value, 4);
+ /* Extract the security layer and the maximum message size */
+ indata = output_token.value;
+ sec_layer = indata[0];
+ max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+
+ /* Free the challenge as it is not required anymore */
gss_release_buffer(&unused_status, &output_token);
- /* Extract the security layer */
- sec_layer = indata & 0x000000FF;
+ /* Process the security layer */
if(!(sec_layer & GSSAUTH_P_NONE)) {
- infof(data, "GSSAPI handshake failure (invalid security layer)\n");
+ infof(data, "GSSAPI handshake failure (invalid security layer)");
- gss_release_buffer(&unused_status, &username_token);
return CURLE_BAD_CONTENT_ENCODING;
}
+ sec_layer &= GSSAUTH_P_NONE; /* We do not support a security layer */
- /* Extract the maximum message size the server can receive */
- max_size = ntohl(indata & 0xFFFFFF00);
+ /* Process the maximum message size the server can receive */
if(max_size > 0) {
/* The server has told us it supports a maximum receive buffer, however, as
we don't require one unless we are encrypting data, we tell the server
@@ -266,26 +246,24 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
}
/* Allocate our message */
- messagelen = sizeof(outdata) + username_token.length + 1;
+ messagelen = 4;
+ if(authzid)
+ messagelen += strlen(authzid);
message = malloc(messagelen);
- if(!message) {
- gss_release_buffer(&unused_status, &username_token);
+ if(!message)
return CURLE_OUT_OF_MEMORY;
- }
- /* Populate the message with the security layer, client supported receive
- message size and authorization identity including the 0x00 based
- terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization
- identity is not terminated with the zero-valued (%x00) octet." it seems
- necessary to include it. */
- outdata = htonl(max_size) | sec_layer;
- memcpy(message, &outdata, sizeof(outdata));
- memcpy(message + sizeof(outdata), username_token.value,
- username_token.length);
- message[messagelen - 1] = '\0';
-
- /* Free the username token as it is not required anymore */
- gss_release_buffer(&unused_status, &username_token);
+ /* Populate the message with the security layer and client supported receive
+ message size. */
+ message[0] = sec_layer & 0xFF;
+ message[1] = (max_size >> 16) & 0xFF;
+ message[2] = (max_size >> 8) & 0xFF;
+ message[3] = max_size & 0xFF;
+
+ /* If given, append the authorization identity. */
+
+ if(authzid && *authzid)
+ memcpy(message + 4, authzid, messagelen - 4);
/* Setup the "authentication data" security buffer */
input_token.value = message;
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index e11064422..c652fd736 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -173,7 +173,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
if(chlg) {
if(!Curl_bufref_len(chlg)) {
- infof(data, "GSSAPI handshake failure (empty challenge message)\n");
+ infof(data, "GSSAPI handshake failure (empty challenge message)");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -238,13 +238,15 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
* Parameters:
*
* data [in] - The session handle.
- * chlg [in] - The optional challenge message.
+ * authzid [in] - The authorization identity if some.
+ * chlg [in] - The optional challenge message.
* krb5 [in/out] - The Kerberos 5 data struct being used and modified.
* out [out] - The result storage.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
+ const char *authzid,
const struct bufref *chlg,
struct kerberos5data *krb5,
struct bufref *out)
@@ -260,19 +262,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
SecBuffer wrap_buf[3];
SecBufferDesc input_desc;
SecBufferDesc wrap_desc;
- unsigned long indata = 0;
- unsigned long outdata = 0;
+ unsigned char *indata;
unsigned long qop = 0;
unsigned long sec_layer = 0;
unsigned long max_size = 0;
SecPkgContext_Sizes sizes;
- SecPkgCredentials_Names names;
SECURITY_STATUS status;
- char *user_name;
+
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) data;
+#endif
/* Ensure we have a valid challenge message */
if(!Curl_bufref_len(chlg)) {
- infof(data, "GSSAPI handshake failure (empty security message)\n");
+ infof(data, "GSSAPI handshake failure (empty security message)");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -287,17 +290,6 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(status != SEC_E_OK)
return CURLE_AUTH_ERROR;
- /* Get the fully qualified username back from the context */
- status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
- SECPKG_CRED_ATTR_NAMES,
- &names);
-
- if(status == SEC_E_INSUFFICIENT_MEMORY)
- return CURLE_OUT_OF_MEMORY;
-
- if(status != SEC_E_OK)
- return CURLE_AUTH_ERROR;
-
/* Setup the "input" security buffer */
input_desc.ulVersion = SECBUFFER_VERSION;
input_desc.cBuffers = 2;
@@ -312,29 +304,32 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
/* Decrypt the inbound challenge and obtain the qop */
status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
if(status != SEC_E_OK) {
- infof(data, "GSSAPI handshake failure (empty security message)\n");
+ infof(data, "GSSAPI handshake failure (empty security message)");
return CURLE_BAD_CONTENT_ENCODING;
}
/* Not 4 octets long so fail as per RFC4752 Section 3.1 */
if(input_buf[1].cbBuffer != 4) {
- infof(data, "GSSAPI handshake failure (invalid security data)\n");
+ infof(data, "GSSAPI handshake failure (invalid security data)");
return CURLE_BAD_CONTENT_ENCODING;
}
- /* Copy the data out and free the challenge as it is not required anymore */
- memcpy(&indata, input_buf[1].pvBuffer, 4);
+ /* Extract the security layer and the maximum message size */
+ indata = input_buf[1].pvBuffer;
+ sec_layer = indata[0];
+ max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+
+ /* Free the challenge as it is not required anymore */
s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
- /* Extract the security layer */
- sec_layer = indata & 0x000000FF;
+ /* Process the security layer */
if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
- infof(data, "GSSAPI handshake failure (invalid security layer)\n");
+ infof(data, "GSSAPI handshake failure (invalid security layer)");
return CURLE_BAD_CONTENT_ENCODING;
}
+ sec_layer &= KERB_WRAP_NO_ENCRYPT; /* We do not support a security layer */
- /* Extract the maximum message size the server can receive */
- max_size = ntohl(indata & 0xFFFFFF00);
+ /* Process the maximum message size the server can receive */
if(max_size > 0) {
/* The server has told us it supports a maximum receive buffer, however, as
we don't require one unless we are encrypting data, we tell the server
@@ -347,33 +342,28 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
if(!trailer)
return CURLE_OUT_OF_MEMORY;
- /* Convert the user name to UTF8 when operating with Unicode */
- user_name = curlx_convert_tchar_to_UTF8(names.sUserName);
- if(!user_name) {
- free(trailer);
-
- return CURLE_OUT_OF_MEMORY;
- }
-
/* Allocate our message */
- messagelen = sizeof(outdata) + strlen(user_name) + 1;
+ messagelen = 4;
+ if(authzid)
+ messagelen += strlen(authzid);
message = malloc(messagelen);
if(!message) {
free(trailer);
- curlx_unicodefree(user_name);
return CURLE_OUT_OF_MEMORY;
}
- /* Populate the message with the security layer, client supported receive
- message size and authorization identity including the 0x00 based
- terminator. Note: Despite RFC4752 Section 3.1 stating "The authorization
- identity is not terminated with the zero-valued (%x00) octet." it seems
- necessary to include it. */
- outdata = htonl(max_size) | sec_layer;
- memcpy(message, &outdata, sizeof(outdata));
- strcpy((char *) message + sizeof(outdata), user_name);
- curlx_unicodefree(user_name);
+ /* Populate the message with the security layer and client supported receive
+ message size. */
+ message[0] = sec_layer & 0xFF;
+ message[1] = (max_size >> 16) & 0xFF;
+ message[2] = (max_size >> 8) & 0xFF;
+ message[3] = max_size & 0xFF;
+
+ /* If given, append the authorization identity. */
+
+ if(authzid && *authzid)
+ memcpy(message + 4, authzid, messagelen - 4);
/* Allocate the padding */
padding = malloc(sizes.cbBlockSize);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index 47e53572c..0aa3f1c8c 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -182,7 +182,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
(target_info_offset + target_info_len) > type2len ||
target_info_offset < 48) {
infof(data, "NTLM handshake failure (bad type-2 message). "
- "Target Info Offset Len is set incorrect by the peer\n");
+ "Target Info Offset Len is set incorrect by the peer");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -286,7 +286,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
(memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
(memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
/* This was not a good enough type-2 message */
- infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ infof(data, "NTLM handshake failure (bad type-2 message)");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -296,7 +296,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
result = ntlm_decode_type2_target(data, type2ref, ntlm);
if(result) {
- infof(data, "NTLM handshake failure (bad type-2 message)\n");
+ infof(data, "NTLM handshake failure (bad type-2 message)");
return result;
}
}
@@ -533,7 +533,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* Get the machine's un-qualified host name as NTLM doesn't like the fully
qualified domain name */
if(Curl_gethostname(host, sizeof(host))) {
- infof(data, "gethostname() failed, continuing without!\n");
+ infof(data, "gethostname() failed, continuing without!");
hostlen = 0;
}
else {
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index 1b1a17630..3e39dad31 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -206,7 +206,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
/* Ensure we have a valid type-2 message */
if(!Curl_bufref_len(type2)) {
- infof(data, "NTLM handshake failure (empty type-2 message)\n");
+ infof(data, "NTLM handshake failure (empty type-2 message)");
return CURLE_BAD_CONTENT_ENCODING;
}
@@ -253,6 +253,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned long attrs;
TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+ (void) data;
+#endif
(void) passwdp;
(void) userp;
@@ -309,7 +312,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
&type_3_desc,
&attrs, &expiry);
if(status != SEC_E_OK) {
- infof(data, "NTLM handshake failure (type-3 message): Status=%x\n",
+ infof(data, "NTLM handshake failure (type-3 message): Status=%x",
status);
if(status == SEC_E_INSUFFICIENT_MEMORY)
diff --git a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
index 120925ff3..8e8932bd0 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -137,8 +137,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
/* Ensure we have a valid challenge message */
if(!chlg) {
- infof(data, "SPNEGO handshake failure (empty challenge message)\n");
-
+ infof(data, "SPNEGO handshake failure (empty challenge message)");
return CURLE_BAD_CONTENT_ENCODING;
}
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index 4aa1ba957..68bb17da5 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -191,8 +191,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
/* Ensure we have a valid challenge message */
if(!chlg) {
- infof(data, "SPNEGO handshake failure (empty challenge message)\n");
-
+ infof(data, "SPNEGO handshake failure (empty challenge message)");
return CURLE_BAD_CONTENT_ENCODING;
}
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index ec5b0007f..47a7c0bc8 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -194,6 +194,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security
token message */
CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
+ const char *authzid,
const struct bufref *chlg,
struct kerberos5data *krb5,
struct bufref *out);
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index b67b9a466..c84ef85fb 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -75,28 +75,26 @@
#endif
#ifdef HAVE_BROTLI
-static size_t brotli_version(char *buf, size_t bufsz)
+static void brotli_version(char *buf, size_t bufsz)
{
uint32_t brotli_version = BrotliDecoderVersion();
unsigned int major = brotli_version >> 24;
unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12;
unsigned int patch = brotli_version & 0x00000FFF;
-
- return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+ (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
}
#endif
#ifdef HAVE_ZSTD
-static size_t zstd_version(char *buf, size_t bufsz)
+static void zstd_version(char *buf, size_t bufsz)
{
unsigned long zstd_version = (unsigned long)ZSTD_versionNumber();
unsigned int major = (unsigned int)(zstd_version / (100 * 100));
unsigned int minor = (unsigned int)((zstd_version -
- (major * 100 * 100)) / 100);
+ (major * 100 * 100)) / 100);
unsigned int patch = (unsigned int)(zstd_version -
- (major * 100 * 100) - (minor * 100));
-
- return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+ (major * 100 * 100) - (minor * 100));
+ (void)msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
}
#endif
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index 7f076759b..9fcfe81a8 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -28,6 +28,9 @@
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/err.h>
+#include <ngtcp2/ngtcp2_crypto_openssl.h>
+#elif defined(USE_GNUTLS)
+#include <ngtcp2/ngtcp2_crypto_gnutls.h>
#endif
#include "urldata.h"
#include "sendf.h"
@@ -86,7 +89,8 @@ struct h3out {
#define QUIC_PRIORITY \
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
- "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
+ "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
+ "%DISABLE_TLS13_COMPAT_MODE"
#endif
static CURLcode ng_process_ingress(struct Curl_easy *data,
@@ -116,42 +120,6 @@ static void quic_printf(void *user_data, const char *fmt, ...)
}
#endif
-#ifdef USE_OPENSSL
-static ngtcp2_crypto_level
-quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level)
-{
- switch(ossl_level) {
- case ssl_encryption_initial:
- return NGTCP2_CRYPTO_LEVEL_INITIAL;
- case ssl_encryption_early_data:
- return NGTCP2_CRYPTO_LEVEL_EARLY;
- case ssl_encryption_handshake:
- return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- case ssl_encryption_application:
- return NGTCP2_CRYPTO_LEVEL_APPLICATION;
- default:
- assert(0);
- }
-}
-#elif defined(USE_GNUTLS)
-static ngtcp2_crypto_level
-quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
-{
- switch(gtls_level) {
- case GNUTLS_ENCRYPTION_LEVEL_INITIAL:
- return NGTCP2_CRYPTO_LEVEL_INITIAL;
- case GNUTLS_ENCRYPTION_LEVEL_EARLY:
- return NGTCP2_CRYPTO_LEVEL_EARLY;
- case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
- return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
- return NGTCP2_CRYPTO_LEVEL_APPLICATION;
- default:
- assert(0);
- }
-}
-#endif
-
static void qlog_callback(void *user_data, uint32_t flags,
const void *data, size_t datalen)
{
@@ -222,27 +190,9 @@ static int write_client_handshake(struct quicsocket *qs,
ngtcp2_crypto_level level,
const uint8_t *data, size_t len)
{
- struct quic_handshake *crypto_data;
int rv;
- crypto_data = &qs->crypto_data[level];
- if(!crypto_data->buf) {
- crypto_data->buf = malloc(4096);
- if(!crypto_data->buf)
- return 0;
- crypto_data->alloclen = 4096;
- }
-
- /* TODO Just pretend that handshake does not grow more than 4KiB for
- now */
- assert(crypto_data->len + len <= crypto_data->alloclen);
-
- memcpy(&crypto_data->buf[crypto_data->len], data, len);
- crypto_data->len += len;
-
- rv = ngtcp2_conn_submit_crypto_data(
- qs->qconn, level, (uint8_t *)(&crypto_data->buf[crypto_data->len] - len),
- len);
+ rv = ngtcp2_conn_submit_crypto_data(qs->qconn, level, data, len);
if(rv) {
H3BUGF(fprintf(stderr, "write_client_handshake failed\n"));
}
@@ -259,7 +209,7 @@ static int quic_set_encryption_secrets(SSL *ssl,
size_t secretlen)
{
struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- int level = quic_from_ossl_level(ossl_level);
+ int level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
if(ngtcp2_crypto_derive_and_install_rx_key(
qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
@@ -281,7 +231,8 @@ static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
const uint8_t *data, size_t len)
{
struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- ngtcp2_crypto_level level = quic_from_ossl_level(ossl_level);
+ ngtcp2_crypto_level level =
+ ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
return write_client_handshake(qs, level, data, len);
}
@@ -369,7 +320,8 @@ static int secret_func(gnutls_session_t ssl,
const void *tx_secret, size_t secretlen)
{
struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- int level = quic_from_gtls_level(gtls_level);
+ int level =
+ ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
ngtcp2_crypto_derive_and_install_rx_key(
@@ -394,7 +346,8 @@ static int read_func(gnutls_session_t ssl,
size_t len)
{
struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- ngtcp2_crypto_level level = quic_from_gtls_level(gtls_level);
+ ngtcp2_crypto_level level =
+ ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
int rv;
if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
@@ -542,22 +495,6 @@ static int quic_init_ssl(struct quicsocket *qs)
}
#endif
-static int
-cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t *data, size_t datalen,
- void *user_data)
-{
- (void)offset;
- (void)user_data;
-
- if(ngtcp2_crypto_read_write_crypto_data(tconn, crypto_level, data,
- datalen) != 0)
- return NGTCP2_ERR_CRYPTO;
-
- return 0;
-}
-
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
(void)user_data;
@@ -622,8 +559,8 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
return 0;
}
-static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
- uint64_t app_error_code,
+static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
+ int64_t stream_id, uint64_t app_error_code,
void *user_data, void *stream_user_data)
{
struct quicsocket *qs = (struct quicsocket *)user_data;
@@ -632,6 +569,10 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
/* stream is closed... */
+ if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
+ app_error_code = NGHTTP3_H3_NO_ERROR;
+ }
+
rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
app_error_code);
if(rv) {
@@ -652,7 +593,25 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
(void)app_error_code;
(void)stream_user_data;
- rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
+ rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
+{
+ struct quicsocket *qs = (struct quicsocket *)user_data;
+ int rv;
+ (void)tconn;
+ (void)app_error_code;
+ (void)stream_user_data;
+
+ rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -712,14 +671,13 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
- cb_recv_crypto_data,
+ ngtcp2_crypto_recv_crypto_data_cb,
cb_handshake_completed,
NULL, /* recv_version_negotiation */
ngtcp2_crypto_encrypt_cb,
ngtcp2_crypto_decrypt_cb,
ngtcp2_crypto_hp_mask_cb,
cb_recv_stream_data,
- NULL, /* acked_crypto_offset */
cb_acked_stream_data_offset,
NULL, /* stream_open */
cb_stream_close,
@@ -744,7 +702,9 @@ static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
NULL, /* recv_datagram */
NULL, /* ack_datagram */
- NULL /* lost_datagram */
+ NULL, /* lost_datagram */
+ NULL, /* get_path_challenge_data */
+ cb_stream_stop_sending
};
/*
@@ -778,7 +738,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- infof(data, "Connect socket %d over QUIC to %s:%d\n",
+ infof(data, "Connect socket %d over QUIC to %s:%d",
sockfd, ipbuf, port);
qs->version = NGTCP2_PROTO_VER_MAX;
@@ -827,15 +787,14 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
}
/*
- * Store ngtp2 version info in this buffer, Prefix with a space. Return total
- * length written.
+ * Store ngtcp2 version info in this buffer.
*/
-int Curl_quic_ver(char *p, size_t len)
+void Curl_quic_ver(char *p, size_t len)
{
const ngtcp2_info *ng2 = ngtcp2_version(0);
nghttp3_info *ht3 = nghttp3_version(0);
- return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
- ng2->version_str, ht3->version_str);
+ (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
+ ng2->version_str, ht3->version_str);
}
static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
@@ -859,7 +818,6 @@ static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
static void qs_disconnect(struct quicsocket *qs)
{
- int i;
if(!qs->conn) /* already closed */
return;
qs->conn = NULL;
@@ -880,8 +838,6 @@ static void qs_disconnect(struct quicsocket *qs)
qs->cred = NULL;
}
#endif
- for(i = 0; i < 3; i++)
- Curl_safefree(qs->crypto_data[i].buf);
nghttp3_conn_del(qs->h3conn);
ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
@@ -951,7 +907,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
(void)stream_id;
(void)app_error_code;
(void)user_data;
- H3BUGF(infof(data, "cb_h3_stream_close CALLED\n"));
+ H3BUGF(infof(data, "cb_h3_stream_close CALLED"));
stream->closed = TRUE;
Curl_expire(data, 0, EXPIRE_QUIC);
@@ -1143,14 +1099,10 @@ static nghttp3_callbacks ngh3_callbacks = {
NULL, /* begin_trailers */
cb_h3_recv_header,
NULL, /* end_trailers */
- NULL, /* http_begin_push_promise */
- NULL, /* http_recv_push_promise */
- NULL, /* http_end_push_promise */
- NULL, /* http_cancel_push */
cb_h3_send_stop_sending,
- NULL, /* push_stream */
NULL, /* end_stream */
NULL, /* reset_stream */
+ NULL /* shutdown */
};
static int init_ngh3_conn(struct quicsocket *qs)
@@ -1287,7 +1239,7 @@ static ssize_t ngh3_stream_recv(struct Curl_easy *data,
return 0;
}
- infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
+ infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN");
*curlcode = CURLE_AGAIN;
return -1;
}
@@ -1304,7 +1256,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
if(!data->set.postfields) {
stream->h3out->used -= datalen;
H3BUGF(infof(data,
- "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
+ "cb_h3_acked_stream_data, %zd bytes, %zd left unacked",
datalen, stream->h3out->used));
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
@@ -1366,13 +1318,13 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
if(!stream->upload_left)
*pflags = NGHTTP3_DATA_FLAG_EOF;
}
- H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n",
+ H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)",
nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
out->used));
}
if(stream->upload_done && !stream->upload_len &&
(stream->upload_left <= 0)) {
- H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
+ H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF"));
*pflags = NGHTTP3_DATA_FLAG_EOF;
return nread ? 1 : 0;
}
@@ -1565,7 +1517,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
"headers exceeds %d bytes and that could cause the "
- "stream to be rejected.\n", MAX_ACC);
+ "stream to be rejected.", MAX_ACC);
}
}
@@ -1611,7 +1563,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
Curl_safefree(nva);
- infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
+ infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
stream3_id, (void *)data);
return CURLE_OK;
@@ -1641,7 +1593,7 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data,
sent = len;
}
else {
- H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
+ H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes",
len));
if(!stream->upload_len) {
stream->upload_mem = mem;
@@ -1660,6 +1612,12 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data,
return -1;
}
+ /* Reset post upload buffer after resumed. */
+ if(stream->upload_mem) {
+ stream->upload_mem = NULL;
+ stream->upload_len = 0;
+ }
+
*curlcode = CURLE_OK;
return sent;
}
@@ -1758,8 +1716,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
int rv;
ssize_t sent;
ssize_t outlen;
- uint8_t out[NGTCP2_MAX_PKTLEN_IPV4];
- size_t pktlen;
+ uint8_t out[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
ngtcp2_path_storage ps;
ngtcp2_tstamp ts = timestamp();
struct sockaddr_storage remote_addr;
@@ -1772,19 +1729,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
ssize_t ndatalen;
uint32_t flags;
- switch(qs->local_addr.ss_family) {
- case AF_INET:
- pktlen = NGTCP2_MAX_PKTLEN_IPV4;
- break;
-#ifdef ENABLE_IPV6
- case AF_INET6:
- pktlen = NGTCP2_MAX_PKTLEN_IPV6;
- break;
-#endif
- default:
- assert(0);
- }
-
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv) {
failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
@@ -1811,15 +1755,16 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
(fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out,
+ sizeof(out),
&ndatalen, flags, stream_id,
(const ngtcp2_vec *)vec, veccnt, ts);
if(outlen == 0) {
break;
}
if(outlen < 0) {
- if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
- outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ switch(outlen) {
+ case NGTCP2_ERR_STREAM_DATA_BLOCKED:
assert(ndatalen == -1);
rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
if(rv) {
@@ -1828,8 +1773,17 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
return CURLE_SEND_ERROR;
}
continue;
- }
- else if(outlen == NGTCP2_ERR_WRITE_MORE) {
+ case NGTCP2_ERR_STREAM_SHUT_WR:
+ assert(ndatalen == -1);
+ rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id);
+ if(rv) {
+ failf(data,
+ "nghttp3_conn_shutdown_stream_write returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
+ continue;
+ case NGTCP2_ERR_WRITE_MORE:
assert(ndatalen >= 0);
rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
if(rv) {
@@ -1838,8 +1792,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
return CURLE_SEND_ERROR;
}
continue;
- }
- else {
+ default:
assert(ndatalen == -1);
failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.h b/Utilities/cmcurl/lib/vquic/ngtcp2.h
index cbede4514..501453042 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.h
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.h
@@ -34,13 +34,6 @@
#include <gnutls/gnutls.h>
#endif
-struct quic_handshake {
- char *buf; /* pointer to the buffer */
- size_t alloclen; /* size of allocation */
- size_t len; /* size of content in buffer */
- size_t nread; /* how many bytes have been read */
-};
-
struct quicsocket {
struct connectdata *conn; /* point back to the connection */
ngtcp2_conn *qconn;
@@ -56,7 +49,6 @@ struct quicsocket {
gnutls_certificate_credentials_t cred;
gnutls_session_t ssl;
#endif
- struct quic_handshake crypto_data[3];
/* the last TLS alert description generated by the local endpoint */
uint8_t tls_alert;
struct sockaddr_storage local_addr;
diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c
index b62d88437..f7577605c 100644
--- a/Utilities/cmcurl/lib/vquic/quiche.c
+++ b/Utilities/cmcurl/lib/vquic/quiche.c
@@ -258,7 +258,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- infof(data, "Connect socket %d over QUIC to %s:%ld\n",
+ infof(data, "Connect socket %d over QUIC to %s:%ld",
sockfd, ipbuf, port);
Curl_persistconninfo(data, conn, NULL, -1);
@@ -277,7 +277,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
offset += 1 + alpn_len;
}
- infof(data, "Sent QUIC client Initial, ALPN: %s\n",
+ infof(data, "Sent QUIC client Initial, ALPN: %s",
alpn_protocols + 1);
}
@@ -345,7 +345,7 @@ CURLcode Curl_quic_is_connected(struct Curl_easy *data,
if(quiche_conn_is_established(qs->conn)) {
*done = TRUE;
result = quiche_has_connected(conn, 0, sockindex);
- DEBUGF(infof(data, "quiche established connection!\n"));
+ DEBUGF(infof(data, "quiche established connection!"));
}
return result;
@@ -422,10 +422,9 @@ static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
return CURLE_SEND_ERROR;
}
- sent = sendto(sockfd, out, sent, 0,
- (struct sockaddr *)&send_info.to, send_info.to_len);
+ sent = send(sockfd, out, sent, 0);
if(sent < 0) {
- failf(data, "sendto() returned %zd", sent);
+ failf(data, "send() returned %zd", sent);
return CURLE_SEND_ERROR;
}
} while(1);
@@ -492,7 +491,7 @@ static ssize_t h3_stream_recv(struct Curl_easy *data,
headers.nlen = 0;
if(process_ingress(data, sockfd, qs)) {
- infof(data, "h3_stream_recv returns on ingress\n");
+ infof(data, "h3_stream_recv returns on ingress");
*curlcode = CURLE_RECV_ERROR;
return -1;
}
@@ -505,7 +504,7 @@ static ssize_t h3_stream_recv(struct Curl_easy *data,
if(s != stream->stream3_id) {
/* another transfer, ignore for now */
- infof(data, "Got h3 for stream %u, expects %u\n",
+ infof(data, "Got h3 for stream %u, expects %u",
s, stream->stream3_id);
continue;
}
@@ -586,7 +585,7 @@ static ssize_t h3_stream_send(struct Curl_easy *data,
sent = len;
}
else {
- H3BUGF(infof(data, "Pass on %zd body bytes to quiche\n", len));
+ H3BUGF(infof(data, "Pass on %zd body bytes to quiche", len));
sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
(uint8_t *)mem, len, FALSE);
if(sent < 0) {
@@ -605,12 +604,11 @@ static ssize_t h3_stream_send(struct Curl_easy *data,
}
/*
- * Store quiche version info in this buffer, Prefix with a space. Return total
- * length written.
+ * Store quiche version info in this buffer.
*/
-int Curl_quic_ver(char *p, size_t len)
+void Curl_quic_ver(char *p, size_t len)
{
- return msnprintf(p, len, "quiche/%s", quiche_version());
+ (void)msnprintf(p, len, "quiche/%s", quiche_version());
}
/* Index where :authority header field will appear in request header
@@ -780,7 +778,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
for(i = 0; i < nheader; ++i) {
acc += nva[i].name_len + nva[i].value_len;
- H3BUGF(infof(data, "h3 [%.*s: %.*s]\n",
+ H3BUGF(infof(data, "h3 [%.*s: %.*s]",
nva[i].name_len, nva[i].name,
nva[i].value_len, nva[i].value));
}
@@ -788,7 +786,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
"headers exceeds %d bytes and that could cause the "
- "stream to be rejected.\n", MAX_ACC);
+ "stream to be rejected.", MAX_ACC);
}
}
@@ -825,13 +823,13 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
Curl_safefree(nva);
if(stream3_id < 0) {
- H3BUGF(infof(data, "quiche_h3_send_request returned %d\n",
+ H3BUGF(infof(data, "quiche_h3_send_request returned %d",
stream3_id));
result = CURLE_SEND_ERROR;
goto fail;
}
- infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
+ infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
stream3_id, (void *)data);
stream->stream3_id = stream3_id;
diff --git a/Utilities/cmcurl/lib/vssh/libssh.c b/Utilities/cmcurl/lib/vssh/libssh.c
index d146d15fd..3e317e87c 100644
--- a/Utilities/cmcurl/lib/vssh/libssh.c
+++ b/Utilities/cmcurl/lib/vssh/libssh.c
@@ -74,7 +74,6 @@
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
-#include "strerror.h"
#include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
@@ -303,7 +302,7 @@ static void mystate(struct Curl_easy *data, sshstate nowstate
if(sshc->state != nowstate) {
- infof(data, "SSH %p state change from %s to %s (line %d)\n",
+ infof(data, "SSH %p state change from %s to %s (line %d)",
(void *) sshc, names[sshc->state], names[nowstate],
lineno);
}
@@ -368,7 +367,7 @@ static int myssh_is_known(struct Curl_easy *data)
for(i = 0; i < 16; i++)
msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]);
- infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
+ infof(data, "SSH MD5 fingerprint: %s", md5buffer);
if(!strcasecompare(md5buffer, pubkey_md5)) {
failf(data,
@@ -732,7 +731,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
- infof(data, "Authenticated with none\n");
+ infof(data, "Authenticated with none");
state(data, SSH_AUTH_DONE);
break;
}
@@ -744,7 +743,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
state(data, SSH_AUTH_PKEY_INIT);
- infof(data, "Authentication using SSH public key file\n");
+ infof(data, "Authentication using SSH public key file");
}
else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
state(data, SSH_AUTH_GSSAPI);
@@ -810,7 +809,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
rc = SSH_OK;
sshc->authed = TRUE;
- infof(data, "Completed public key authentication\n");
+ infof(data, "Completed public key authentication");
state(data, SSH_AUTH_DONE);
break;
}
@@ -827,12 +826,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
- infof(data, "Completed public key authentication\n");
+ infof(data, "Completed public key authentication");
state(data, SSH_AUTH_DONE);
break;
}
else {
- infof(data, "Failed public key authentication (rc: %d)\n", rc);
+ infof(data, "Failed public key authentication (rc: %d)", rc);
MOVE_TO_SECONDARY_AUTH;
}
break;
@@ -852,7 +851,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
rc = SSH_OK;
sshc->authed = TRUE;
- infof(data, "Completed gssapi authentication\n");
+ infof(data, "Completed gssapi authentication");
state(data, SSH_AUTH_DONE);
break;
}
@@ -878,7 +877,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(rc == SSH_OK) {
sshc->authed = TRUE;
- infof(data, "completed keyboard interactive authentication\n");
+ infof(data, "completed keyboard interactive authentication");
}
state(data, SSH_AUTH_DONE);
break;
@@ -901,7 +900,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == SSH_AUTH_SUCCESS) {
sshc->authed = TRUE;
- infof(data, "Completed password authentication\n");
+ infof(data, "Completed password authentication");
state(data, SSH_AUTH_DONE);
}
else {
@@ -919,7 +918,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/*
* At this point we have an authenticated ssh session.
*/
- infof(data, "Authentication complete\n");
+ infof(data, "Authentication complete");
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
@@ -930,7 +929,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_SFTP_INIT);
break;
}
- infof(data, "SSH CONNECT phase done\n");
+ infof(data, "SSH CONNECT phase done");
state(data, SSH_STOP);
break;
@@ -970,7 +969,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
we get the homedir here, we get the "workingpath" in the DO action
since the homedir will remain the same between request but the
working path will not. */
- DEBUGF(infof(data, "SSH CONNECT phase done\n"));
+ DEBUGF(infof(data, "SSH CONNECT phase done"));
state(data, SSH_STOP);
break;
@@ -983,7 +982,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(data->set.quote) {
- infof(data, "Sending quote commands\n");
+ infof(data, "Sending quote commands");
sshc->quote_item = data->set.quote;
state(data, SSH_SFTP_QUOTE);
}
@@ -994,7 +993,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_POSTQUOTE_INIT:
if(data->set.postquote) {
- infof(data, "Sending quote commands\n");
+ infof(data, "Sending quote commands");
sshc->quote_item = data->set.postquote;
state(data, SSH_SFTP_QUOTE);
}
@@ -1367,7 +1366,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'\n", protop->path);
+ infof(data, "Creating directory '%s'", protop->path);
state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
@@ -1731,7 +1730,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
if(data->req.size == 0) {
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- infof(data, "File already completely downloaded\n");
+ infof(data, "File already completely downloaded");
state(data, SSH_STOP);
break;
}
@@ -1764,7 +1763,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
Curl_safefree(protop->path);
- DEBUGF(infof(data, "SFTP DONE done\n"));
+ DEBUGF(infof(data, "SFTP DONE done"));
/* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
After nextstate is executed, the control should come back to
@@ -1933,7 +1932,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
if(rc != SSH_OK) {
- infof(data, "Failed to close libssh scp channel: %s\n",
+ infof(data, "Failed to close libssh scp channel: %s",
ssh_get_error(sshc->ssh_session));
}
}
@@ -1946,7 +1945,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_scp_free(sshc->scp_session);
sshc->scp_session = NULL;
}
- DEBUGF(infof(data, "SCP DONE phase complete\n"));
+ DEBUGF(infof(data, "SCP DONE phase complete"));
ssh_set_blocking(sshc->ssh_session, 0);
@@ -2213,7 +2212,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
if(conn->user && conn->user[0] != '\0') {
- infof(data, "User: %s\n", conn->user);
+ infof(data, "User: %s", conn->user);
rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
if(rc != SSH_OK) {
failf(data, "Could not set user");
@@ -2222,7 +2221,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
- infof(data, "Known hosts: %s\n", data->set.str[STRING_SSH_KNOWNHOSTS]);
+ infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
data->set.str[STRING_SSH_KNOWNHOSTS]);
if(rc != SSH_OK) {
@@ -2279,7 +2278,7 @@ static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
}
@@ -2300,7 +2299,7 @@ CURLcode scp_perform(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
@@ -2312,7 +2311,7 @@ CURLcode scp_perform(struct Curl_easy *data,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -2481,7 +2480,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
@@ -2494,7 +2493,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -2506,7 +2505,7 @@ static CURLcode sftp_doing(struct Curl_easy *data,
{
CURLcode result = myssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
}
@@ -2521,7 +2520,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void) dead_connection;
- DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
@@ -2529,7 +2528,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
result = myssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done"));
return result;
@@ -2940,9 +2939,9 @@ void Curl_ssh_cleanup(void)
(void)ssh_finalize();
}
-size_t Curl_ssh_version(char *buffer, size_t buflen)
+void Curl_ssh_version(char *buffer, size_t buflen)
{
- return msnprintf(buffer, buflen, "libssh/%s", CURL_LIBSSH_VERSION);
+ (void)msnprintf(buffer, buflen, "libssh/%s", CURL_LIBSSH_VERSION);
}
#endif /* USE_LIBSSH */
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 8a6345b94..a772f1f9b 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -73,7 +73,6 @@
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
-#include "strerror.h"
#include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
@@ -378,7 +377,7 @@ static void state(struct Curl_easy *data, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(data, "SFTP %p state change from %s to %s\n",
+ infof(data, "SFTP %p state change from %s to %s",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -491,7 +490,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
break;
#endif
default:
- infof(data, "unsupported key type, can't check knownhosts!\n");
+ infof(data, "unsupported key type, can't check knownhosts!");
keybit = 0;
break;
}
@@ -519,7 +518,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
&host);
#endif
- infof(data, "SSH host check: %d, key: %s\n", keycheck,
+ infof(data, "SSH host check: %d, key: %s", keycheck,
(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");
@@ -586,7 +585,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
LIBSSH2_KNOWNHOST_KEYENC_RAW|
keybit, NULL);
if(addrc)
- infof(data, "Warning adding the known host %s failed!\n",
+ infof(data, "Warning adding the known host %s failed!",
conn->host.name);
else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
rc == CURLKHSTAT_FINE_REPLACE) {
@@ -597,7 +596,7 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(wrc) {
- infof(data, "Warning, writing %s failed!\n",
+ infof(data, "Warning, writing %s failed!",
data->set.str[STRING_SSH_KNOWNHOSTS]);
}
}
@@ -626,7 +625,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
int i;
for(i = 0; i < 16; i++)
msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
- infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
+ infof(data, "SSH MD5 fingerprint: %s", md5buffer);
}
/* Before we authenticate we check the hostkey's MD5 fingerprint
@@ -645,7 +644,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data)
sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
return sshc->actualcode;
}
- infof(data, "MD5 checksum match!\n");
+ infof(data, "MD5 checksum match!");
/* as we already matched, we skip the check for known hosts */
return CURLE_OK;
}
@@ -702,7 +701,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
if(store->name[0] == '[') {
kh_name_end = strstr(store->name, "]:");
if(!kh_name_end) {
- infof(data, "Invalid host pattern %s in %s\n",
+ infof(data, "Invalid host pattern %s in %s",
store->name, data->set.str[STRING_SSH_KNOWNHOSTS]);
continue;
}
@@ -729,7 +728,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
}
if(found) {
- infof(data, "Found host %s in %s\n",
+ infof(data, "Found host %s in %s",
conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
@@ -768,13 +767,13 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
return CURLE_SSH;
}
- infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
+ infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
result = libssh2_session_error_to_CURLE(
libssh2_session_method_pref(
sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
}
else {
- infof(data, "Did not find host %s in %s\n",
+ infof(data, "Did not find host %s in %s",
conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
}
}
@@ -874,7 +873,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(!sshc->authlist) {
if(libssh2_userauth_authenticated(sshc->ssh_session)) {
sshc->authed = TRUE;
- infof(data, "SSH user accepted with no authentication\n");
+ infof(data, "SSH user accepted with no authentication");
state(data, SSH_AUTH_DONE);
break;
}
@@ -887,7 +886,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
break;
}
- infof(data, "SSH authentication methods available: %s\n",
+ infof(data, "SSH authentication methods available: %s",
sshc->authlist);
state(data, SSH_AUTH_PKEY_INIT);
@@ -972,8 +971,8 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->passphrase = "";
if(sshc->rsa_pub)
- infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
- infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
+ infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
+ infof(data, "Using SSH private key file '%s'", sshc->rsa);
state(data, SSH_AUTH_PKEY);
}
@@ -1000,14 +999,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == 0) {
sshc->authed = TRUE;
- infof(data, "Initialized SSH public key authentication\n");
+ infof(data, "Initialized SSH public key authentication");
state(data, SSH_AUTH_DONE);
}
else {
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "SSH public key authentication failed: %s\n", err_msg);
+ infof(data, "SSH public key authentication failed: %s", err_msg);
state(data, SSH_AUTH_PASS_INIT);
rc = 0; /* clear rc and continue */
}
@@ -1035,7 +1034,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(rc == 0) {
sshc->authed = TRUE;
- infof(data, "Initialized password authentication\n");
+ infof(data, "Initialized password authentication");
state(data, SSH_AUTH_DONE);
}
else {
@@ -1069,7 +1068,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(!sshc->ssh_agent) {
sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
if(!sshc->ssh_agent) {
- infof(data, "Could not create agent object\n");
+ infof(data, "Could not create agent object");
state(data, SSH_AUTH_KEY_INIT);
break;
@@ -1080,7 +1079,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN)
break;
if(rc < 0) {
- infof(data, "Failure connecting to agent\n");
+ infof(data, "Failure connecting to agent");
state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
@@ -1100,7 +1099,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(rc == LIBSSH2_ERROR_EAGAIN)
break;
if(rc < 0) {
- infof(data, "Failure requesting identities to agent\n");
+ infof(data, "Failure requesting identities to agent");
state(data, SSH_AUTH_KEY_INIT);
rc = 0; /* clear rc and continue */
}
@@ -1136,13 +1135,13 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(rc < 0)
- infof(data, "Failure requesting identities to agent\n");
+ infof(data, "Failure requesting identities to agent");
else if(rc == 1)
- infof(data, "No identity would match\n");
+ infof(data, "No identity would match");
if(rc == LIBSSH2_ERROR_NONE) {
sshc->authed = TRUE;
- infof(data, "Agent based authentication successful\n");
+ infof(data, "Agent based authentication successful");
state(data, SSH_AUTH_DONE);
}
else {
@@ -1174,7 +1173,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(rc == 0) {
sshc->authed = TRUE;
- infof(data, "Initialized keyboard interactive authentication\n");
+ infof(data, "Initialized keyboard interactive authentication");
}
state(data, SSH_AUTH_DONE);
break;
@@ -1190,7 +1189,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/*
* At this point we have an authenticated ssh session.
*/
- infof(data, "Authentication complete\n");
+ infof(data, "Authentication complete");
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
@@ -1201,7 +1200,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_SFTP_INIT);
break;
}
- infof(data, "SSH CONNECT phase done\n");
+ infof(data, "SSH CONNECT phase done");
state(data, SSH_STOP);
break;
@@ -1261,7 +1260,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
a time-out or similar */
result = CURLE_SSH;
sshc->actualcode = result;
- DEBUGF(infof(data, "error = %lu makes libcurl = %d\n",
+ DEBUGF(infof(data, "error = %lu makes libcurl = %d",
sftperr, (int)result));
state(data, SSH_STOP);
break;
@@ -1271,7 +1270,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
we get the homedir here, we get the "workingpath" in the DO action
since the homedir will remain the same between request but the
working path will not. */
- DEBUGF(infof(data, "SSH CONNECT phase done\n"));
+ DEBUGF(infof(data, "SSH CONNECT phase done"));
state(data, SSH_STOP);
break;
@@ -1285,7 +1284,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(data->set.quote) {
- infof(data, "Sending quote commands\n");
+ infof(data, "Sending quote commands");
sshc->quote_item = data->set.quote;
state(data, SSH_SFTP_QUOTE);
}
@@ -1296,7 +1295,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
case SSH_SFTP_POSTQUOTE_INIT:
if(data->set.postquote) {
- infof(data, "Sending quote commands\n");
+ infof(data, "Sending quote commands");
sshc->quote_item = data->set.postquote;
state(data, SSH_SFTP_QUOTE);
}
@@ -2048,7 +2047,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(sshc->slash_pos) {
*sshc->slash_pos = 0;
- infof(data, "Creating directory '%s'\n", sshp->path);
+ infof(data, "Creating directory '%s'", sshp->path);
state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
break;
}
@@ -2411,7 +2410,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
if(data->req.size == 0) {
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- infof(data, "File already completely downloaded\n");
+ infof(data, "File already completely downloaded");
state(data, SSH_STOP);
break;
}
@@ -2446,14 +2445,14 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
+ infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
Curl_safefree(sshp->path);
- DEBUGF(infof(data, "SFTP DONE done\n"));
+ DEBUGF(infof(data, "SFTP DONE done"));
/* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
After nextstate is executed, the control should come back to
@@ -2483,7 +2482,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
NULL, 0);
- infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
+ infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
@@ -2493,7 +2492,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to stop libssh2 sftp subsystem\n");
+ infof(data, "Failed to stop libssh2 sftp subsystem");
}
sshc->sftp_session = NULL;
}
@@ -2668,7 +2667,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
+ infof(data, "Failed to send libssh2 channel EOF: %d %s",
rc, err_msg);
}
}
@@ -2685,7 +2684,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
+ infof(data, "Failed to get channel EOF: %d %s", rc, err_msg);
}
}
state(data, SSH_SCP_WAIT_CLOSE);
@@ -2701,7 +2700,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
+ infof(data, "Channel failed to close: %d %s", rc, err_msg);
}
}
state(data, SSH_SCP_CHANNEL_FREE);
@@ -2717,12 +2716,12 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s",
rc, err_msg);
}
sshc->ssh_channel = NULL;
}
- DEBUGF(infof(data, "SCP DONE phase complete\n"));
+ DEBUGF(infof(data, "SCP DONE phase complete"));
#if 0 /* PREV */
state(data, SSH_SESSION_DISCONNECT);
#endif
@@ -2743,7 +2742,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s",
rc, err_msg);
}
sshc->ssh_channel = NULL;
@@ -2758,7 +2757,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to disconnect libssh2 session: %d %s\n",
+ infof(data, "Failed to disconnect libssh2 session: %d %s",
rc, err_msg);
}
}
@@ -2787,7 +2786,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to disconnect from libssh2 agent: %d %s\n",
+ infof(data, "Failed to disconnect from libssh2 agent: %d %s",
rc, err_msg);
}
libssh2_agent_free(sshc->ssh_agent);
@@ -2809,7 +2808,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
- infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg);
+ infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
}
sshc->ssh_session = NULL;
}
@@ -2938,6 +2937,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
+ struct curltime dis = Curl_now();
while((sshc->state != SSH_STOP) && !result) {
bool block;
@@ -2962,6 +2962,12 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
return CURLE_OPERATION_TIMEDOUT;
}
}
+ else if(Curl_timediff(now, dis) > 1000) {
+ /* disconnect timeout */
+ failf(data, "Disconnect timed out");
+ result = CURLE_OK;
+ break;
+ }
if(block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
@@ -3078,10 +3084,10 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
#ifdef CURL_LIBSSH2_DEBUG
if(conn->user) {
- infof(data, "User: %s\n", conn->user);
+ infof(data, "User: %s", conn->user);
}
if(conn->passwd) {
- infof(data, "Password: %s\n", conn->passwd);
+ infof(data, "Password: %s", conn->passwd);
}
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
@@ -3115,7 +3121,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
sshrecv.recvptr = ssh_tls_recv;
sshsend.sendptr = ssh_tls_send;
- infof(data, "Uses HTTPS proxy!\n");
+ infof(data, "Uses HTTPS proxy!");
/*
Setup libssh2 callbacks to make it read/write TLS from the socket.
@@ -3153,7 +3159,7 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
#if LIBSSH2_VERSION_NUM >= 0x010208
if(libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
#endif
- infof(data, "Failed to enable compression for ssh session\n");
+ infof(data, "Failed to enable compression for ssh session");
}
#ifdef HAVE_LIBSSH2_KNOWNHOST_API
@@ -3171,14 +3177,14 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
data->set.str[STRING_SSH_KNOWNHOSTS],
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
if(rc < 0)
- infof(data, "Failed to read known hosts from %s\n",
+ infof(data, "Failed to read known hosts from %s",
data->set.str[STRING_SSH_KNOWNHOSTS]);
}
#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
#ifdef CURL_LIBSSH2_DEBUG
libssh2_trace(sshc->ssh_session, ~0);
- infof(data, "SSH socket: %d\n", (int)sock);
+ infof(data, "SSH socket: %d", (int)sock);
#endif /* CURL_LIBSSH2_DEBUG */
state(data, SSH_INIT);
@@ -3205,7 +3211,7 @@ CURLcode scp_perform(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
@@ -3218,7 +3224,7 @@ CURLcode scp_perform(struct Curl_easy *data,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -3232,7 +3238,7 @@ static CURLcode scp_doing(struct Curl_easy *data,
result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
}
@@ -3394,7 +3400,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
@@ -3407,7 +3413,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
*connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -3420,7 +3426,7 @@ static CURLcode sftp_doing(struct Curl_easy *data,
CURLcode result = ssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
}
@@ -3435,7 +3441,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now"));
if(sshc->ssh_session) {
/* only if there's a session still around to use! */
@@ -3443,7 +3449,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
result = ssh_block_statemach(data, conn, TRUE);
}
- DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done"));
return result;
@@ -3602,9 +3608,9 @@ void Curl_ssh_cleanup(void)
#endif
}
-size_t Curl_ssh_version(char *buffer, size_t buflen)
+void Curl_ssh_version(char *buffer, size_t buflen)
{
- return msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION);
+ (void)msnprintf(buffer, buflen, "libssh2/%s", LIBSSH2_VERSION);
}
/* The SSH session is associated with the *CONNECTION* but the callback user
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 505b0787c..7972081ec 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -262,7 +262,7 @@ extern const struct Curl_handler Curl_handler_sftp;
/* generic SSH backend functions */
CURLcode Curl_ssh_init(void);
void Curl_ssh_cleanup(void);
-size_t Curl_ssh_version(char *buffer, size_t buflen);
+void Curl_ssh_version(char *buffer, size_t buflen);
void Curl_ssh_attach(struct Curl_easy *data,
struct connectdata *conn);
#else
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index 9f3266a24..4b1e2ec5e 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -205,7 +205,7 @@ static void state(struct Curl_easy *data, sshstate nowstate)
DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
if(sshc->state != nowstate) {
- infof(data, "wolfssh %p state change from %s to %s\n",
+ infof(data, "wolfssh %p state change from %s to %s",
(void *)sshc, names[sshc->state], names[nowstate]);
}
#endif
@@ -274,7 +274,7 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
return -1;
}
DEBUGASSERT(rc == (int)len);
- infof(data, "sent %zd bytes SFTP from offset %zd\n",
+ infof(data, "sent %zd bytes SFTP from offset %zd",
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
@@ -348,7 +348,7 @@ static int userauth(byte authtype,
void *ctx)
{
struct Curl_easy *data = ctx;
- DEBUGF(infof(data, "wolfssh callback: type %s\n",
+ DEBUGF(infof(data, "wolfssh callback: type %s",
authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
"PUBLICCKEY"));
if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
@@ -468,7 +468,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_STOP);
return CURLE_SSH;
}
- infof(data, "wolfssh connected!\n");
+ infof(data, "wolfssh connected!");
state(data, SSH_STOP);
break;
case SSH_STOP:
@@ -489,7 +489,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- infof(data, "wolfssh SFTP connected!\n");
+ infof(data, "wolfssh SFTP connected!");
state(data, SSH_SFTP_REALPATH);
}
else {
@@ -518,7 +518,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
else {
memcpy(sshc->homedir, name->fName, name->fSz);
sshc->homedir[name->fSz] = 0;
- infof(data, "wolfssh SFTP realpath succeeded!\n");
+ infof(data, "wolfssh SFTP realpath succeeded!");
}
wolfSSH_SFTPNAME_list_free(name);
state(data, SSH_STOP);
@@ -536,7 +536,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
if(data->set.quote) {
- infof(data, "Sending quote commands\n");
+ infof(data, "Sending quote commands");
sshc->quote_item = data->set.quote;
state(data, SSH_SFTP_QUOTE);
}
@@ -616,7 +616,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- infof(data, "wolfssh SFTP open succeeded!\n");
+ infof(data, "wolfssh SFTP open succeeded!");
}
else {
failf(data, "wolfssh SFTP upload open failed: %d", rc);
@@ -727,7 +727,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- infof(data, "wolfssh SFTP open succeeded!\n");
+ infof(data, "wolfssh SFTP open succeeded!");
state(data, SSH_SFTP_DOWNLOAD_STAT);
return CURLE_OK;
}
@@ -753,7 +753,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(rc == WS_SUCCESS) {
- infof(data, "wolfssh STAT succeeded!\n");
+ infof(data, "wolfssh STAT succeeded!");
}
else {
failf(data, "wolfssh SFTP open failed: %d", rc);
@@ -769,12 +769,12 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
data->req.maxdownload = size;
Curl_pgrsSetDownloadSize(data, size);
- infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size);
+ infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes", size);
/* We cannot seek with wolfSSH so resuming and range requests are not
possible */
if(data->state.use_range || data->state.resume_from) {
- infof(data, "wolfSSH cannot do range/seek on SFTP\n");
+ infof(data, "wolfSSH cannot do range/seek on SFTP");
return CURLE_BAD_DOWNLOAD_RESUME;
}
@@ -782,7 +782,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
if(data->req.size == 0) {
/* no data to transfer */
Curl_setup_transfer(data, -1, -1, FALSE, -1);
- infof(data, "File already completely downloaded\n");
+ infof(data, "File already completely downloaded");
state(data, SSH_STOP);
break;
}
@@ -911,7 +911,7 @@ static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done)
/* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
try again */
if(*done) {
- DEBUGF(infof(data, "wssh_statemach_act says DONE\n"));
+ DEBUGF(infof(data, "wssh_statemach_act says DONE"));
}
} while(!result && !*done && !block);
@@ -937,7 +937,7 @@ CURLcode wsftp_perform(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
- DEBUGF(infof(data, "DO phase starts\n"));
+ DEBUGF(infof(data, "DO phase starts"));
*dophase_done = FALSE; /* not done yet */
@@ -950,7 +950,7 @@ CURLcode wsftp_perform(struct Curl_easy *data,
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
@@ -1107,7 +1107,7 @@ static CURLcode wsftp_doing(struct Curl_easy *data,
CURLcode result = wssh_multi_statemach(data, dophase_done);
if(*dophase_done) {
- DEBUGF(infof(data, "DO phase is complete\n"));
+ DEBUGF(infof(data, "DO phase is complete"));
}
return result;
}
@@ -1119,7 +1119,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data,
CURLcode result = CURLE_OK;
(void)dead;
- DEBUGF(infof(data, "SSH DISCONNECT starts now\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT starts now"));
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
@@ -1127,7 +1127,7 @@ static CURLcode wsftp_disconnect(struct Curl_easy *data,
result = wssh_block_statemach(data, TRUE);
}
- DEBUGF(infof(data, "SSH DISCONNECT is done\n"));
+ DEBUGF(infof(data, "SSH DISCONNECT is done"));
return result;
}
@@ -1148,9 +1148,9 @@ static int wssh_getsock(struct Curl_easy *data,
return bitmap;
}
-size_t Curl_ssh_version(char *buffer, size_t buflen)
+void Curl_ssh_version(char *buffer, size_t buflen)
{
- return msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING);
+ (void)msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING);
}
CURLcode Curl_ssh_init(void)
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 7f729713d..e87649e2a 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -68,6 +68,14 @@ struct cafile_parser {
size_t dn_len;
};
+#define CAFILE_SOURCE_PATH 1
+#define CAFILE_SOURCE_BLOB 2
+struct cafile_source {
+ const int type;
+ const char * const data;
+ const size_t len;
+};
+
static void append_dn(void *ctx, const void *buf, size_t len)
{
struct cafile_parser *ca = ctx;
@@ -90,7 +98,8 @@ static void x509_push(void *ctx, const void *buf, size_t len)
br_x509_decoder_push(&ca->xc, buf, len);
}
-static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
+static CURLcode load_cafile(struct cafile_source *source,
+ br_x509_trust_anchor **anchors,
size_t *anchors_len)
{
struct cafile_parser ca;
@@ -100,13 +109,22 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
br_x509_trust_anchor *new_anchors;
size_t new_anchors_len;
br_x509_pkey *pkey;
- FILE *fp;
- unsigned char buf[BUFSIZ], *p;
+ FILE *fp = 0;
+ unsigned char buf[BUFSIZ];
+ const unsigned char *p;
const char *name;
size_t n, i, pushed;
- fp = fopen(path, "rb");
- if(!fp)
+ DEBUGASSERT(source->type == CAFILE_SOURCE_PATH
+ || source->type == CAFILE_SOURCE_BLOB);
+
+ if(source->type == CAFILE_SOURCE_PATH) {
+ fp = fopen(source->data, "rb");
+ if(!fp)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+
+ if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX)
return CURLE_SSL_CACERT_BADFILE;
ca.err = CURLE_OK;
@@ -115,11 +133,17 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
ca.anchors_len = 0;
br_pem_decoder_init(&pc);
br_pem_decoder_setdest(&pc, x509_push, &ca);
- for(;;) {
- n = fread(buf, 1, sizeof(buf), fp);
- if(n == 0)
- break;
- p = buf;
+ do {
+ if(source->type == CAFILE_SOURCE_PATH) {
+ n = fread(buf, 1, sizeof(buf), fp);
+ if(n == 0)
+ break;
+ p = buf;
+ }
+ else if(source->type == CAFILE_SOURCE_BLOB) {
+ n = source->len;
+ p = (unsigned char *) source->data;
+ }
while(n) {
pushed = br_pem_decoder_push(&pc, p, n);
if(ca.err)
@@ -211,12 +235,13 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
goto fail;
}
}
- }
- if(ferror(fp))
+ } while(source->type != CAFILE_SOURCE_BLOB);
+ if(fp && ferror(fp))
ca.err = CURLE_READ_ERROR;
fail:
- fclose(fp);
+ if(fp)
+ fclose(fp);
if(ca.err == CURLE_OK) {
*anchors = ca.anchors;
*anchors_len = ca.anchors_len;
@@ -299,8 +324,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
- const char * const hostname = SSL_HOST_NAME();
+ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
+ const char *hostname = SSL_HOST_NAME();
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
CURLcode ret;
@@ -340,8 +368,30 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
+ if(ca_info_blob) {
+ struct cafile_source source = {
+ CAFILE_SOURCE_BLOB,
+ ca_info_blob->data,
+ ca_info_blob->len,
+ };
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
+ if(ret != CURLE_OK) {
+ if(verifypeer) {
+ failf(data, "error importing CA certificate blob");
+ return ret;
+ }
+ /* Only warn if no certificate verification is required. */
+ infof(data, "error importing CA certificate blob, continuing anyway");
+ }
+ }
+
if(ssl_cafile) {
- ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
+ struct cafile_source source = {
+ CAFILE_SOURCE_PATH,
+ ssl_cafile,
+ 0,
+ };
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
failf(data, "error setting certificate verify locations."
@@ -349,7 +399,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
return ret;
}
infof(data, "error setting certificate verify locations,"
- " continuing anyway:\n");
+ " continuing anyway:");
}
}
@@ -373,7 +423,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
&session, NULL, sockindex)) {
br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
- infof(data, "BearSSL: re-using session ID\n");
+ infof(data, "BearSSL: re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -392,12 +442,12 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
#endif
) {
backend->protocols[cur++] = ALPN_H2;
- infof(data, "ALPN, offering %s\n", ALPN_H2);
+ infof(data, "ALPN, offering %s", ALPN_H2);
}
#endif
backend->protocols[cur++] = ALPN_HTTP_1_1;
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
br_ssl_engine_set_protocol_names(&backend->ctx.eng,
backend->protocols, cur);
@@ -538,7 +588,7 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
if(protocol) {
- infof(data, "ALPN, server accepted to use %s\n", protocol);
+ infof(data, "ALPN, server accepted to use %s", protocol);
#ifdef USE_HTTP2
if(!strcmp(protocol, ALPN_H2))
@@ -548,12 +598,12 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
if(!strcmp(protocol, ALPN_HTTP_1_1))
conn->negnpn = CURL_HTTP_VERSION_1_1;
else
- infof(data, "ALPN, unrecognized protocol %s\n", protocol);
+ infof(data, "ALPN, unrecognized protocol %s", protocol);
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
}
if(SSL_SET_OPTION(primary.sessionid)) {
@@ -840,30 +890,32 @@ static CURLcode bearssl_sha256sum(const unsigned char *input,
}
const struct Curl_ssl Curl_ssl_bearssl = {
- { CURLSSLBACKEND_BEARSSL, "bearssl" },
- 0,
+ { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
+ SSLSUPP_CAINFO_BLOB,
sizeof(struct ssl_backend_data),
- Curl_none_init,
- Curl_none_cleanup,
- bearssl_version,
- Curl_none_check_cxn,
- Curl_none_shutdown,
- bearssl_data_pending,
- bearssl_random,
- Curl_none_cert_status_request,
- bearssl_connect,
- bearssl_connect_nonblocking,
- Curl_ssl_getsock,
- bearssl_get_internals,
- bearssl_close,
- Curl_none_close_all,
- bearssl_session_free,
- Curl_none_set_engine,
- Curl_none_set_engine_default,
- Curl_none_engines_list,
- Curl_none_false_start,
- bearssl_sha256sum
+ Curl_none_init, /* init */
+ Curl_none_cleanup, /* cleanup */
+ bearssl_version, /* version */
+ Curl_none_check_cxn, /* check_cxn */
+ Curl_none_shutdown, /* shutdown */
+ bearssl_data_pending, /* data_pending */
+ bearssl_random, /* random */
+ Curl_none_cert_status_request, /* cert_status_request */
+ bearssl_connect, /* connect */
+ bearssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_ssl_getsock, /* getsock */
+ bearssl_get_internals, /* get_internals */
+ bearssl_close, /* close_one */
+ Curl_none_close_all, /* close_all */
+ bearssl_session_free, /* session_free */
+ Curl_none_set_engine, /* set_engine */
+ Curl_none_set_engine_default, /* set_engine_default */
+ Curl_none_engines_list, /* engines_list */
+ Curl_none_false_start, /* false_start */
+ bearssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+ NULL /* disassociate_connection */
};
#endif /* USE_BEARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index ca953769d..e451f6aeb 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -180,6 +180,7 @@ static bool is_separator(char c)
static CURLcode gskit_status(struct Curl_easy *data, int rc,
const char *procname, CURLcode defcode)
{
+ char buffer[STRERROR_LEN];
/* Process GSKit status and map it to a CURLcode. */
switch(rc) {
case GSK_OK:
@@ -208,7 +209,8 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
case ENOMEM:
return CURLE_OUT_OF_MEMORY;
default:
- failf(data, "%s I/O error: %s", procname, strerror(errno));
+ failf(data, "%s I/O error: %s", procname,
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
}
break;
@@ -223,13 +225,15 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_enum(h, id, value);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_enum() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
@@ -245,13 +249,15 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
@@ -267,6 +273,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
static CURLcode set_numeric(struct Curl_easy *data,
gsk_handle h, GSK_NUM_ID id, int value)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_numeric_value(h, id, value);
switch(rc) {
@@ -274,7 +281,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
return CURLE_OK;
case GSK_ERROR_IO:
failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
- strerror(errno));
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
default:
failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
@@ -287,13 +294,15 @@ static CURLcode set_numeric(struct Curl_easy *data,
static CURLcode set_callback(struct Curl_easy *data,
gsk_handle h, GSK_CALLBACK_ID id, void *info)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_callback(h, id, info);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_callback() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
default:
failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
@@ -966,7 +975,9 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data,
continue; /* Retry. */
}
if(errno != ETIME) {
- failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "QsoWaitForIOCompletion() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
cancel_async_handshake(conn, sockindex);
close_async_handshake(connssl);
return CURLE_SSL_CONNECT_ERROR;
@@ -1011,7 +1022,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data,
CURLE_OK) {
int i;
- infof(data, "Server certificate:\n");
+ infof(data, "Server certificate:");
p = cdev;
for(i = 0; i++ < cdec; p++)
switch(p->cert_data_id) {
@@ -1020,16 +1031,16 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data,
certend = cert + cdev->cert_data_l;
break;
case CERT_DN_PRINTABLE:
- infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
+ infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p);
break;
case CERT_ISSUER_DN_PRINTABLE:
- infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
+ infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p);
break;
case CERT_VALID_FROM:
- infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p);
break;
case CERT_VALID_TO:
- infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p);
break;
}
}
@@ -1192,6 +1203,7 @@ static int gskit_shutdown(struct Curl_easy *data,
int what;
int rc;
char buf[120];
+ int loop = 10; /* don't get stuck */
if(!BACKEND->handle)
return 0;
@@ -1206,7 +1218,7 @@ static int gskit_shutdown(struct Curl_easy *data,
what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
- for(;;) {
+ while(loop--) {
ssize_t nread;
if(what < 0) {
@@ -1228,7 +1240,8 @@ static int gskit_shutdown(struct Curl_easy *data,
nread = read(conn->sock[sockindex], buf, sizeof(buf));
if(nread < 0) {
- failf(data, "read: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
rc = -1;
}
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index ecde5c44d..1b145d8eb 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -147,7 +147,7 @@ static void showtime(struct Curl_easy *data,
msnprintf(str,
sizeof(str),
- "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
+ " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
text,
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
@@ -156,7 +156,7 @@ static void showtime(struct Curl_easy *data,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- infof(data, "%s\n", str);
+ infof(data, "%s", str);
}
#endif
@@ -266,7 +266,7 @@ static CURLcode handshake(struct Curl_easy *data,
if(!strerr)
strerr = gnutls_strerror(rc);
- infof(data, "gnutls_handshake() warning: %s\n", strerr);
+ infof(data, "gnutls_handshake() warning: %s", strerr);
continue;
}
else if(rc < 0) {
@@ -330,6 +330,9 @@ set_ssl_version_min_max(struct Curl_easy *data,
ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
}
}
+ else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
+ }
switch(ssl_version | ssl_version_max) {
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
@@ -338,11 +341,11 @@ set_ssl_version_min_max(struct Curl_easy *data,
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.0:+VERS-TLS1.1";
+ "+VERS-TLS1.1:+VERS-TLS1.0";
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2";
+ "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
@@ -350,7 +353,7 @@ set_ssl_version_min_max(struct Curl_easy *data,
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.1:+VERS-TLS1.2";
+ "+VERS-TLS1.2:+VERS-TLS1.1";
return CURLE_OK;
case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
@@ -360,25 +363,16 @@ set_ssl_version_min_max(struct Curl_easy *data,
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
"+VERS-TLS1.3";
return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
- *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2"
- ":+VERS-TLS1.3";
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
- *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.1:+VERS-TLS1.2"
- ":+VERS-TLS1.3";
+ case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
+ *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
+ case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.2"
- ":+VERS-TLS1.3";
+ "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
+ case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
*prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
- "+VERS-TLS1.2"
- ":+VERS-TLS1.3";
+ "+VERS-TLS1.3:+VERS-TLS1.2";
return CURLE_OK;
}
@@ -438,7 +432,7 @@ gtls_connect_step1(struct Curl_easy *data,
#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
- infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
+ infof(data, "Using TLS-SRP username: %s", SSL_SET_OPTION(username));
rc = gnutls_srp_allocate_client_credentials(
&backend->srp_client_cred);
@@ -468,7 +462,7 @@ gtls_connect_step1(struct Curl_easy *data,
SSL_CONN_CONFIG(CAfile),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)\n",
+ infof(data, "error reading ca cert file %s (%s)",
SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
if(SSL_CONN_CONFIG(verifypeer)) {
*certverifyresult = rc;
@@ -476,7 +470,7 @@ gtls_connect_step1(struct Curl_easy *data,
}
}
else
- infof(data, "found %d certificates in %s\n", rc,
+ infof(data, "found %d certificates in %s", rc,
SSL_CONN_CONFIG(CAfile));
}
@@ -486,7 +480,7 @@ gtls_connect_step1(struct Curl_easy *data,
SSL_CONN_CONFIG(CApath),
GNUTLS_X509_FMT_PEM);
if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)\n",
+ infof(data, "error reading ca cert file %s (%s)",
SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
if(SSL_CONN_CONFIG(verifypeer)) {
*certverifyresult = rc;
@@ -494,7 +488,7 @@ gtls_connect_step1(struct Curl_easy *data,
}
}
else
- infof(data, "found %d certificates in %s\n",
+ infof(data, "found %d certificates in %s",
rc, SSL_CONN_CONFIG(CApath));
}
@@ -517,7 +511,7 @@ gtls_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CRL_BADFILE;
}
else
- infof(data, "found %d CRL in %s\n",
+ infof(data, "found %d CRL in %s",
rc, SSL_SET_OPTION(CRLfile));
}
@@ -550,7 +544,7 @@ gtls_connect_step1(struct Curl_easy *data,
(gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
strlen(hostname)) < 0))
infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
+ "TLS extension");
/* Use default priorities */
rc = gnutls_set_default_priority(session);
@@ -603,11 +597,12 @@ gtls_connect_step1(struct Curl_easy *data,
free(prioritysrp);
if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
- infof(data, "This GnuTLS does not support SRP\n");
+ infof(data, "This GnuTLS does not support SRP");
}
}
else {
#endif
+ infof(data, "GnuTLS ciphers: %s", prioritylist);
rc = gnutls_priority_set_direct(session, prioritylist, &err);
#ifdef HAVE_GNUTLS_SRP
}
@@ -632,14 +627,14 @@ gtls_connect_step1(struct Curl_easy *data,
protocols[cur].data = (unsigned char *)ALPN_H2;
protocols[cur].size = ALPN_H2_LENGTH;
cur++;
- infof(data, "ALPN, offering %.*s\n", ALPN_H2_LENGTH, ALPN_H2);
+ infof(data, "ALPN, offering %.*s", ALPN_H2_LENGTH, ALPN_H2);
}
#endif
protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
cur++;
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
gnutls_alpn_set_protocols(session, protocols, cur, 0);
}
@@ -745,7 +740,7 @@ gtls_connect_step1(struct Curl_easy *data,
gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
/* Informational message */
- infof(data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -848,7 +843,7 @@ gtls_connect_step3(struct Curl_easy *data,
gnutls_cipher_get(session),
gnutls_mac_get(session));
- infof(data, "SSL connection using %s / %s\n",
+ infof(data, "SSL connection using %s / %s",
gnutls_protocol_get_name(version), ptr);
/* This function will return the peer's raw certificate (chain) as sent by
@@ -861,7 +856,7 @@ gtls_connect_step3(struct Curl_easy *data,
if(!chainp) {
if(SSL_CONN_CONFIG(verifypeer) ||
SSL_CONN_CONFIG(verifyhost) ||
- SSL_SET_OPTION(issuercert)) {
+ SSL_CONN_CONFIG(issuercert)) {
#ifdef HAVE_GNUTLS_SRP
if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
&& SSL_SET_OPTION(username) != NULL
@@ -879,7 +874,7 @@ gtls_connect_step3(struct Curl_easy *data,
}
#endif
}
- infof(data, "\t common name: WARNING couldn't obtain\n");
+ infof(data, " common name: WARNING couldn't obtain");
}
if(data->set.ssl.certinfo && chainp) {
@@ -926,13 +921,13 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
}
else
- infof(data, "\t server certificate verification FAILED\n");
+ infof(data, " server certificate verification FAILED");
}
else
- infof(data, "\t server certificate verification OK\n");
+ infof(data, " server certificate verification OK");
}
else
- infof(data, "\t server certificate verification SKIPPED\n");
+ infof(data, " server certificate verification SKIPPED");
if(SSL_CONN_CONFIG(verifystatus)) {
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
@@ -944,7 +939,7 @@ gtls_connect_step3(struct Curl_easy *data,
rc = gnutls_ocsp_status_request_get(session, &status_request);
- infof(data, "\t server certificate status verification FAILED\n");
+ infof(data, " server certificate status verification FAILED");
if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
failf(data, "No OCSP response received");
@@ -1032,10 +1027,10 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_SSL_INVALIDCERTSTATUS;
}
else
- infof(data, "\t server certificate status verification OK\n");
+ infof(data, " server certificate status verification OK");
}
else
- infof(data, "\t server certificate status verification SKIPPED\n");
+ infof(data, " server certificate status verification SKIPPED");
/* initialize an X.509 certificate structure. */
gnutls_x509_crt_init(&x509_cert);
@@ -1045,21 +1040,21 @@ gtls_connect_step3(struct Curl_easy *data,
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
gnutls_x509_crt_init(&x509_issuer);
- issuerp = load_file(SSL_SET_OPTION(issuercert));
+ issuerp = load_file(SSL_CONN_CONFIG(issuercert));
gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
- infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
- SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
+ infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
+ SSL_CONN_CONFIG(issuercert)?SSL_CONN_CONFIG(issuercert):"none");
}
size = sizeof(certname);
@@ -1069,7 +1064,7 @@ gtls_connect_step3(struct Curl_easy *data,
certname,
&size);
if(rc) {
- infof(data, "error fetching CN from cert:%s\n",
+ infof(data, "error fetching CN from cert:%s",
gnutls_strerror(rc));
}
@@ -1129,11 +1124,11 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
}
else
- infof(data, "\t common name: %s (does not match '%s')\n",
+ infof(data, " common name: %s (does not match '%s')",
certname, SSL_HOST_DISPNAME());
}
else
- infof(data, "\t common name: %s (matched)\n", certname);
+ infof(data, " common name: %s (matched)", certname);
/* Check for time-based validity */
certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
@@ -1146,7 +1141,7 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
else
- infof(data, "\t server certificate expiration date verify FAILED\n");
+ infof(data, " server certificate expiration date verify FAILED");
}
else {
if(certclock < time(NULL)) {
@@ -1157,10 +1152,10 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
}
else
- infof(data, "\t server certificate expiration date FAILED\n");
+ infof(data, " server certificate expiration date FAILED");
}
else
- infof(data, "\t server certificate expiration date OK\n");
+ infof(data, " server certificate expiration date OK");
}
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
@@ -1173,7 +1168,7 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
else
- infof(data, "\t server certificate activation date verify FAILED\n");
+ infof(data, " server certificate activation date verify FAILED");
}
else {
if(certclock > time(NULL)) {
@@ -1184,10 +1179,10 @@ gtls_connect_step3(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
}
else
- infof(data, "\t server certificate activation date FAILED\n");
+ infof(data, " server certificate activation date FAILED");
}
else
- infof(data, "\t server certificate activation date OK\n");
+ infof(data, " server certificate activation date OK");
}
ptr = SSL_PINNED_PUB_KEY();
@@ -1213,19 +1208,19 @@ gtls_connect_step3(struct Curl_easy *data,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* public key algorithm's parameters */
algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
- infof(data, "\t certificate public key: %s\n",
+ infof(data, " certificate public key: %s",
gnutls_pk_algorithm_get_name(algo));
/* version of the X.509 certificate. */
- infof(data, "\t certificate version: #%d\n",
+ infof(data, " certificate version: #%d",
gnutls_x509_crt_get_version(x509_cert));
rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
if(rc)
- infof(data, "Failed to get certificate name\n");
+ infof(data, "Failed to get certificate name");
else {
- infof(data, "\t subject: %s\n", certfields.data);
+ infof(data, " subject: %s", certfields.data);
certclock = gnutls_x509_crt_get_activation_time(x509_cert);
showtime(data, "start date", certclock);
@@ -1238,9 +1233,9 @@ gtls_connect_step3(struct Curl_easy *data,
rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
if(rc)
- infof(data, "Failed to get certificate issuer\n");
+ infof(data, "Failed to get certificate issuer");
else {
- infof(data, "\t issuer: %s\n", certfields.data);
+ infof(data, " issuer: %s", certfields.data);
gnutls_free(certfields.data);
}
@@ -1251,7 +1246,7 @@ gtls_connect_step3(struct Curl_easy *data,
if(conn->bits.tls_enable_alpn) {
rc = gnutls_alpn_get_selected_protocol(session, &proto);
if(rc == 0) {
- infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
+ infof(data, "ALPN, server accepted to use %.*s", proto.size,
proto.data);
#ifdef USE_HTTP2
@@ -1268,7 +1263,7 @@ gtls_connect_step3(struct Curl_easy *data,
}
}
else
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
@@ -1438,6 +1433,10 @@ static void close_one(struct ssl_connect_data *connssl)
{
struct ssl_backend_data *backend = connssl->backend;
if(backend->session) {
+ char buf[32];
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)gnutls_record_recv(backend->session, buf, sizeof(buf));
gnutls_bye(backend->session, GNUTLS_SHUT_WR);
gnutls_deinit(backend->session);
backend->session = NULL;
@@ -1506,7 +1505,7 @@ static int gtls_shutdown(struct Curl_easy *data, struct connectdata *conn,
break;
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
- infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
+ infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED");
break;
default:
retval = -1;
@@ -1620,7 +1619,7 @@ static bool gtls_cert_status_request(void)
}
static void *gtls_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 3a0be0f04..780d13e18 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -41,7 +41,9 @@
#include <mbedtls/net.h>
#endif
#include <mbedtls/ssl.h>
+#if MBEDTLS_VERSION_NUMBER < 0x03000000
#include <mbedtls/certs.h>
+#endif
#include <mbedtls/x509.h>
#include <mbedtls/error.h>
@@ -89,6 +91,10 @@ struct ssl_backend_data {
#define THREADING_SUPPORT
#endif
+#ifndef MBEDTLS_ERROR_C
+#define mbedtls_strerror(a,b,c) b[0] = 0
+#endif
+
#if defined(THREADING_SUPPORT)
static mbedtls_entropy_context ts_entropy;
@@ -179,6 +185,17 @@ static Curl_send mbed_send;
static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
{
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ switch(version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+#else
switch(version) {
case CURL_SSLVERSION_TLSv1_0:
*mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
@@ -192,6 +209,8 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
case CURL_SSLVERSION_TLSv1_3:
break;
}
+#endif
+
return CURLE_SSL_CONNECT_ERROR;
}
@@ -201,8 +220,13 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
+ int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3;
+#else
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+#endif
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
CURLcode result = CURLE_OK;
@@ -250,12 +274,14 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
const char * const hostname = SSL_HOST_NAME();
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
const long int port = SSL_HOST_PORT();
+#endif
int ret = -1;
char errorbuf[128];
- errorbuf[0] = 0;
if((SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) ||
(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)) {
@@ -270,9 +296,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
&ts_entropy, NULL, 0);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
@@ -283,9 +307,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
&backend->entropy, NULL, 0);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
@@ -298,9 +320,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
if(ret<0) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
ssl_cafile, -ret, errorbuf);
@@ -313,9 +333,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
if(ret<0) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
ssl_capath, -ret, errorbuf);
@@ -331,9 +349,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
ssl_cert, -ret, errorbuf);
@@ -341,27 +357,72 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
}
- /* Load the client private key */
- mbedtls_pk_init(&backend->pk);
-
- if(SSL_SET_OPTION(key)) {
- ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
- SSL_SET_OPTION(key_passwd));
- if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
- mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
- ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ if(ssl_cert_blob) {
+ const unsigned char *blob_data =
+ (const unsigned char *)ssl_cert_blob->data;
+ ret = mbedtls_x509_crt_parse(&backend->clicert, blob_data,
+ ssl_cert_blob->len);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
SSL_SET_OPTION(key), -ret, errorbuf);
-
return CURLE_SSL_CERTPROBLEM;
}
}
+ /* Load the client private key */
+ mbedtls_pk_init(&backend->pk);
+
+ if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) {
+ if(SSL_SET_OPTION(key)) {
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd),
+ mbedtls_ctr_drbg_random,
+ &backend->ctr_drbg);
+#else
+ ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd));
+#endif
+
+ if(ret) {
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
+ SSL_SET_OPTION(key), -ret, errorbuf);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+ else {
+ const struct curl_blob *ssl_key_blob = SSL_SET_OPTION(key_blob);
+ const unsigned char *key_data =
+ (const unsigned char *)ssl_key_blob->data;
+ const char *passwd = SSL_SET_OPTION(key_passwd);
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
+ (const unsigned char *)passwd,
+ passwd ? strlen(passwd) : 0,
+ mbedtls_ctr_drbg_random,
+ &backend->ctr_drbg);
+#else
+ ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
+ (const unsigned char *)passwd,
+ passwd ? strlen(passwd) : 0);
+#endif
+
+ if(ret) {
+ mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
+ failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s",
+ -ret, errorbuf);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
+ mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
+ ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+
/* Load the CRL */
mbedtls_x509_crl_init(&backend->crl);
@@ -369,9 +430,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
ssl_crlfile, -ret, errorbuf);
@@ -379,7 +438,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
}
- infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port);
+ infof(data, "mbedTLS: Connecting to %s:%ld", hostname, port);
mbedtls_ssl_config_init(&backend->config);
@@ -404,10 +463,12 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
+#if MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_1);
- infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
+ infof(data, "mbedTLS: Set min SSL version to TLS 1.0");
break;
+#endif
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
@@ -459,7 +520,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
return CURLE_SSL_CONNECT_ERROR;
}
- infof(data, "mbedTLS re-using session\n");
+ infof(data, "mbedTLS re-using session");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -468,7 +529,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
&backend->cacert,
&backend->crl);
- if(SSL_SET_OPTION(key)) {
+ if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) {
mbedtls_ssl_conf_own_cert(&backend->config,
&backend->clicert, &backend->pk);
}
@@ -497,7 +558,7 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
for(p = &backend->protocols[0]; *p; ++p)
- infof(data, "ALPN, offering %s\n", *p);
+ infof(data, "ALPN, offering %s", *p);
}
#endif
@@ -553,18 +614,14 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
else if(ret) {
char errorbuf[128];
- errorbuf[0] = 0;
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
-ret, errorbuf);
return CURLE_SSL_CONNECT_ERROR;
}
- infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
- mbedtls_ssl_get_ciphersuite(&backend->ssl)
- );
+ infof(data, "mbedTLS: Handshake complete, cipher is %s",
+ mbedtls_ssl_get_ciphersuite(&backend->ssl));
ret = mbedtls_ssl_get_verify_result(&backend->ssl);
@@ -601,9 +658,9 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
- infof(data, "Dumping cert info:\n%s\n", buffer);
+ infof(data, "Dumping cert info: %s", buffer);
else
- infof(data, "Unable to dump certificate information.\n");
+ infof(data, "Unable to dump certificate information");
free(buffer);
}
@@ -611,10 +668,15 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(pinnedpubkey) {
int size;
CURLcode result;
- mbedtls_x509_crt *p;
- unsigned char pubkey[PUB_DER_MAX_BYTES];
+ mbedtls_x509_crt *p = NULL;
+ unsigned char *pubkey = NULL;
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
+ !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
+#else
if(!peercert || !peercert->raw.p || !peercert->raw.len) {
+#endif
failf(data, "Failed due to missing peer certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
@@ -624,39 +686,54 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(!p)
return CURLE_OUT_OF_MEMORY;
+ pubkey = malloc(PUB_DER_MAX_BYTES);
+
+ if(!pubkey) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto pinnedpubkey_error;
+ }
+
mbedtls_x509_crt_init(p);
/* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
needs a non-const key, for now.
https://github.com/ARMmbed/mbedtls/issues/396 */
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(mbedtls_x509_crt_parse_der(p,
+ peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
+ peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
+#else
if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
+#endif
failf(data, "Failed copying peer certificate");
- mbedtls_x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ goto pinnedpubkey_error;
}
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
+ PUB_DER_MAX_BYTES);
+#else
size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
+#endif
if(size <= 0) {
failf(data, "Failed copying public key from peer certificate");
- mbedtls_x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ goto pinnedpubkey_error;
}
/* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
result = Curl_pin_peer_pubkey(data,
pinnedpubkey,
&pubkey[PUB_DER_MAX_BYTES - size], size);
+ pinnedpubkey_error:
+ mbedtls_x509_crt_free(p);
+ free(p);
+ free(pubkey);
if(result) {
- mbedtls_x509_crt_free(p);
- free(p);
return result;
}
-
- mbedtls_x509_crt_free(p);
- free(p);
}
#ifdef HAS_ALPN
@@ -664,7 +741,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
if(next_protocol) {
- infof(data, "ALPN, server accepted to use %s\n", next_protocol);
+ infof(data, "ALPN, server accepted to use %s", next_protocol);
#ifdef USE_NGHTTP2
if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
NGHTTP2_PROTO_VERSION_ID_LEN) &&
@@ -679,7 +756,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
}
else {
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
}
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
@@ -687,7 +764,7 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#endif
connssl->connecting_state = ssl_connect_3;
- infof(data, "SSL connected\n");
+ infof(data, "SSL connected");
return CURLE_OK;
}
@@ -775,8 +852,13 @@ static void mbedtls_close(struct Curl_easy *data,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
-
+ char buf[32];
(void) data;
+
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf));
+
mbedtls_pk_free(&backend->pk);
mbedtls_x509_crt_free(&backend->clicert);
mbedtls_x509_crt_free(&backend->cacert);
@@ -844,15 +926,12 @@ static CURLcode mbedtls_random(struct Curl_easy *data,
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_init(&ctr_entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
- errorbuf[0] = 0;
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&ctr_entropy, NULL, 0);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s",
-ret, errorbuf);
}
@@ -860,9 +939,7 @@ static CURLcode mbedtls_random(struct Curl_easy *data,
ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
if(ret) {
-#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-#endif /* MBEDTLS_ERROR_C */
failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
-ret, errorbuf);
}
@@ -1046,12 +1123,17 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
+ /* TODO: explain this for different mbedtls 2.x vs 3 version */
(void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
#else
/* returns 0 on success, otherwise failure */
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
+#else
if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
+#endif
return CURLE_BAD_FUNCTION_ARGUMENT;
#endif
return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 473f5171e..751755c23 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -55,10 +55,8 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
return 0; /* error, no number of threads defined */
for(i = 0; i < NUMT; i++) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_init(&mutex_buf[i], NULL);
- if(ret)
+ if(pthread_mutex_init(&mutex_buf[i], NULL))
return 0; /* pthread_mutex_init failed */
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
mutex_buf[i] = CreateMutex(0, FALSE, 0);
@@ -78,14 +76,11 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void)
return 0; /* error, no threads locks defined */
for(i = 0; i < NUMT; i++) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_destroy(&mutex_buf[i]);
- if(ret)
+ if(pthread_mutex_destroy(&mutex_buf[i]))
return 0; /* pthread_mutex_destroy failed */
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
- ret = CloseHandle(mutex_buf[i]);
- if(!ret)
+ if(!CloseHandle(mutex_buf[i]))
return 0; /* CloseHandle failed */
#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
}
@@ -98,17 +93,14 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void)
int Curl_mbedtlsthreadlock_lock_function(int n)
{
if(n < NUMT) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_lock(&mutex_buf[n]);
- if(ret) {
+ if(pthread_mutex_lock(&mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
}
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
- ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
- if(ret) {
+ if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
@@ -121,17 +113,14 @@ int Curl_mbedtlsthreadlock_lock_function(int n)
int Curl_mbedtlsthreadlock_unlock_function(int n)
{
if(n < NUMT) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_unlock(&mutex_buf[n]);
- if(ret) {
+ if(pthread_mutex_unlock(&mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_unlock failed */
}
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
- ret = ReleaseMutex(mutex_buf[n]);
- if(!ret) {
+ if(!ReleaseMutex(mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
index bf8600d32..3db9184f7 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.c
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -167,14 +167,14 @@ mesalink_connect_step1(struct Curl_easy *data,
}
infof(data,
"error setting certificate verify locations,"
- " continuing anyway:\n");
+ " continuing anyway:");
}
else {
- infof(data, "successfully set certificate verify locations:\n");
+ infof(data, "successfully set certificate verify locations:");
}
- infof(data, " CAfile: %s\n",
+ infof(data, " CAfile: %s",
SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none");
- infof(data, " CApath: %s\n",
+ infof(data, " CApath: %s",
SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none");
}
@@ -196,7 +196,7 @@ mesalink_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
infof(data,
- "client cert: %s\n",
+ "client cert: %s",
SSL_CONN_CONFIG(clientcert)?
SSL_CONN_CONFIG(clientcert): "none");
}
@@ -209,7 +209,7 @@ mesalink_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CIPHER;
}
#endif
- infof(data, "Cipher selection: %s\n", ciphers);
+ infof(data, "Cipher selection: %s", ciphers);
}
if(BACKEND->handle)
@@ -273,7 +273,7 @@ mesalink_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof(data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -326,7 +326,7 @@ mesalink_connect_step2(struct Curl_easy *data,
connssl->connecting_state = ssl_connect_3;
infof(data,
- "SSL connection using %s / %s\n",
+ "SSL connection using %s / %s",
SSL_get_version(BACKEND->handle),
SSL_get_cipher_name(BACKEND->handle));
@@ -356,7 +356,7 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
+ infof(data, "old SSL session ID is stale, removing");
Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 1582b1e58..cf657895f 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -433,7 +433,7 @@ static char *dup_nickname(struct Curl_easy *data, const char *str)
n = strchr(str, '/');
if(!n) {
infof(data, "warning: certificate file name \"%s\" handled as nickname; "
- "please use \"./%s\" to force file name\n", str, str);
+ "please use \"./%s\" to force file name", str, str);
return strdup(str);
}
@@ -824,7 +824,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
#endif
if(!SSL_CONN_CONFIG(verifypeer)) {
- infof(data, "skipping SSL peer certificate verification\n");
+ infof(data, "skipping SSL peer certificate verification");
return SECSuccess;
}
@@ -857,15 +857,15 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
#endif
case SSL_NEXT_PROTO_NO_SUPPORT:
case SSL_NEXT_PROTO_NO_OVERLAP:
- infof(data, "ALPN/NPN, server did not agree to a protocol\n");
+ infof(data, "ALPN/NPN, server did not agree to a protocol");
return;
#ifdef SSL_ENABLE_ALPN
case SSL_NEXT_PROTO_SELECTED:
- infof(data, "ALPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "ALPN, server accepted to use %.*s", buflen, buf);
break;
#endif
case SSL_NEXT_PROTO_NEGOTIATED:
- infof(data, "NPN, server accepted to use %.*s\n", buflen, buf);
+ infof(data, "NPN, server accepted to use %.*s", buflen, buf);
break;
}
@@ -937,7 +937,7 @@ static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
*canFalseStart = PR_TRUE;
- infof(data, "Trying TLS False Start\n");
+ infof(data, "Trying TLS False Start");
end:
return SECSuccess;
@@ -955,17 +955,17 @@ static void display_cert_info(struct Curl_easy *data,
subject = CERT_NameToAscii(&cert->subject);
issuer = CERT_NameToAscii(&cert->issuer);
common_name = CERT_GetCommonName(&cert->subject);
- infof(data, "\tsubject: %s\n", subject);
+ infof(data, "subject: %s\n", subject);
CERT_GetCertTimes(cert, &notBefore, &notAfter);
PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
- infof(data, "\tstart date: %s\n", timeString);
+ infof(data, " start date: %s", timeString);
PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
- infof(data, "\texpire date: %s\n", timeString);
- infof(data, "\tcommon name: %s\n", common_name);
- infof(data, "\tissuer: %s\n", issuer);
+ infof(data, " expire date: %s", timeString);
+ infof(data, " common name: %s", common_name);
+ infof(data, " issuer: %s", issuer);
PR_Free(subject);
PR_Free(issuer);
@@ -987,13 +987,13 @@ static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
channel.cipherSuite) {
if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
&suite, sizeof(suite)) == SECSuccess) {
- infof(data, "SSL connection using %s\n", suite.cipherSuiteName);
+ infof(data, "SSL connection using %s", suite.cipherSuiteName);
}
}
cert = SSL_PeerCertificate(sock);
if(cert) {
- infof(data, "Server certificate:\n");
+ infof(data, "Server certificate:");
if(!data->set.ssl.certinfo) {
display_cert_info(data, cert);
@@ -1058,7 +1058,7 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
/* print only info about the cert, the error is printed off the callback */
cert = SSL_PeerCertificate(sock);
if(cert) {
- infof(data, "Server certificate:\n");
+ infof(data, "Server certificate:");
display_cert_info(data, cert);
CERT_DestroyCertificate(cert);
}
@@ -1132,7 +1132,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
/* report the resulting status */
switch(result) {
case CURLE_OK:
- infof(data, "pinned public key verified successfully!\n");
+ infof(data, "pinned public key verified successfully!");
break;
case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
failf(data, "failed to verify pinned public key");
@@ -1196,7 +1196,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
return SECFailure;
}
- infof(data, "NSS: client certificate from file\n");
+ infof(data, "NSS: client certificate from file");
display_cert_info(data, cert);
*pRetCert = cert;
@@ -1234,7 +1234,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
return SECFailure;
}
- infof(data, "NSS: using client certificate: %s\n", nickname);
+ infof(data, "NSS: using client certificate: %s", nickname);
display_cert_info(data, *pRetCert);
return SECSuccess;
}
@@ -1355,7 +1355,7 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
if(!certpath)
return CURLE_OUT_OF_MEMORY;
- infof(data, "Initializing NSS with certpath: %s\n", certpath);
+ infof(data, "Initializing NSS with certpath: %s", certpath);
nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
free(certpath);
@@ -1365,10 +1365,10 @@ static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
err = PR_GetError();
err_name = nss_error_to_name(err);
- infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name);
+ infof(data, "Unable to initialize NSS database: %d (%s)", err, err_name);
}
- infof(data, "Initializing NSS with certpath: none\n");
+ infof(data, "Initializing NSS with certpath: none");
nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
| NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
| NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
@@ -1546,6 +1546,14 @@ static void close_one(struct ssl_connect_data *connssl)
const bool client_cert = (backend->client_nickname != NULL)
|| (backend->obj_clicert != NULL);
+ if(backend->handle) {
+ char buf[32];
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)PR_Recv(backend->handle, buf, (int)sizeof(buf), 0,
+ PR_INTERVAL_NO_WAIT);
+ }
+
free(backend->client_nickname);
backend->client_nickname = NULL;
@@ -1650,8 +1658,8 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
if(capath && !capath[0])
capath = NULL;
- infof(data, " CAfile: %s\n", cafile ? cafile : "none");
- infof(data, " CApath: %s\n", capath ? capath : "none");
+ infof(data, " CAfile: %s", cafile ? cafile : "none");
+ infof(data, " CApath: %s", capath ? capath : "none");
/* load libnssckbi.so if no other trust roots were specified */
use_trust_module = !cafile && !capath;
@@ -1660,7 +1668,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
if(use_trust_module && !trust_module) {
/* libnssckbi.so needed but not yet loaded --> load it! */
result = nss_load_module(&trust_module, trust_library, "trust");
- infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
+ infof(data, "%s %s", (result) ? "failed to load" : "loaded",
trust_library);
if(result == CURLE_FAILED_INIT)
/* If libnssckbi.so is not available (or fails to load), one can still
@@ -1669,7 +1677,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
}
else if(!use_trust_module && trust_module) {
/* libnssckbi.so not needed but already loaded --> unload it! */
- infof(data, "unloading %s\n", trust_library);
+ infof(data, "unloading %s", trust_library);
nss_unload_module(&trust_module);
}
PR_Unlock(nss_trustload_lock);
@@ -1702,7 +1710,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
/* This is purposefully tolerant of errors so non-PEM files can
* be in the same directory */
- infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
+ infof(data, "failed to load '%s' from CURLOPT_CAPATH", fullpath);
free(fullpath);
}
@@ -1710,7 +1718,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data,
PR_CloseDir(dir);
}
else
- infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
+ infof(data, "warning: CURLOPT_CAPATH not a directory (%s)", capath);
}
return CURLE_OK;
@@ -1813,7 +1821,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
curlerr = CURLE_SSL_CERTPROBLEM;
/* print the error number and error string */
- infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
+ infof(data, "NSS error %d (%s)", err, nss_error_to_name(err));
/* print a human-readable message describing the error if available */
nss_print_error_message(data, err);
@@ -1887,7 +1895,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
PR_Unlock(nss_initlock);
if(result == CURLE_FAILED_INIT)
infof(data, "WARNING: failed to load NSS PEM library %s. Using "
- "OpenSSL PEM certificates will not work.\n", pem_library);
+ "OpenSSL PEM certificates will not work.", pem_library);
else if(result)
goto error;
@@ -1922,8 +1930,8 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
sslver_req_str = nss_sslver_to_name(sslver.max);
sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
if(sslver_req_str && sslver_supp_str)
- infof(data, "Falling back from %s to max supported SSL version (%s)\n",
- sslver_req_str, sslver_supp_str);
+ infof(data, "Falling back from %s to max supported SSL version (%s)",
+ sslver_req_str, sslver_supp_str);
free(sslver_req_str);
free(sslver_supp_str);
sslver.max = sslver_supported.max;
@@ -1936,11 +1944,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
/* unless the user explicitly asks to allow the protocol vulnerability, we
use the work-around */
if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
- infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
+ infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d",
ssl_cbc_random_iv);
#else
if(ssl_cbc_random_iv)
- infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
+ infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in");
#endif
if(SSL_CONN_CONFIG(cipher_list)) {
@@ -1951,7 +1959,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
}
if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
- infof(data, "warning: ignoring value of ssl.verifyhost\n");
+ infof(data, "warning: ignoring value of ssl.verifyhost");
/* bypass the default SSL_AuthCertificate() hook in case we do not want to
* verify peer */
@@ -1971,7 +1979,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex);
if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
/* not a fatal error because we are not going to verify the peer */
- infof(data, "warning: CA certificates failed to load\n");
+ infof(data, "warning: CA certificates failed to load");
else if(rv) {
result = rv;
goto error;
@@ -1984,7 +1992,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data,
result = rv;
goto error;
}
- infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
+ infof(data, " CRLfile: %s", SSL_SET_OPTION(CRLfile));
}
if(SSL_SET_OPTION(primary.clientcert)) {
@@ -2179,9 +2187,9 @@ static CURLcode nss_do_connect(struct Curl_easy *data,
if(result)
goto error;
- if(SSL_SET_OPTION(issuercert)) {
+ if(SSL_CONN_CONFIG(issuercert)) {
SECStatus ret = SECFailure;
- char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
+ char *nickname = dup_nickname(data, SSL_CONN_CONFIG(issuercert));
if(nickname) {
/* we support only nicknames in case of issuercert for now */
ret = check_issuer_cert(backend->handle, nickname);
@@ -2189,12 +2197,12 @@ static CURLcode nss_do_connect(struct Curl_easy *data,
}
if(SECFailure == ret) {
- infof(data, "SSL certificate issuer check failed\n");
+ infof(data, "SSL certificate issuer check failed");
result = CURLE_SSL_ISSUER_ERROR;
goto error;
}
else {
- infof(data, "SSL certificate issuer check ok\n");
+ infof(data, "SSL certificate issuer check ok");
}
}
@@ -2306,7 +2314,7 @@ static ssize_t nss_send(struct Curl_easy *data, /* transfer */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(data, "SSL write: error %d (%s)\n", err, err_name);
+ infof(data, "SSL write: error %d (%s)", err, err_name);
/* print a human-readable message describing the error if available */
nss_print_error_message(data, err);
@@ -2348,7 +2356,7 @@ static ssize_t nss_recv(struct Curl_easy *data, /* transfer */
else {
/* print the error number and error string */
const char *err_name = nss_error_to_name(err);
- infof(data, "SSL read: errno %d (%s)\n", err, err_name);
+ infof(data, "SSL read: errno %d (%s)", err, err_name);
/* print a human-readable message describing the error if available */
nss_print_error_message(data, err);
@@ -2427,7 +2435,7 @@ static bool nss_false_start(void)
}
static void *nss_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index ebd7abc3b..87f4b02b7 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -194,7 +194,7 @@
!defined(OPENSSL_IS_BORINGSSL))
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
-/* SET_EC_CURVES available under the same preconditions: see
+/* SET_EC_CURVES is available under the same preconditions: see
* https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
*/
#define HAVE_SSL_CTX_SET_EC_CURVES
@@ -209,8 +209,8 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-/* up2date versions of OpenSSL maintain the default reasonably secure without
- * breaking compatibility, so it is better not to override the default by curl
+/* up2date versions of OpenSSL maintain reasonably secure defaults without
+ * breaking compatibility, so it is better not to override the defaults in curl
*/
#define DEFAULT_CIPHER_SELECTION NULL
#else
@@ -435,17 +435,16 @@ static bool rand_enough(void)
static CURLcode ossl_seed(struct Curl_easy *data)
{
- /* we have the "SSL is seeded" boolean static to prevent multiple
- time-consuming seedings in vain */
- static bool ssl_seeded = FALSE;
char fname[256];
- if(ssl_seeded)
+ /* This might get called before it has been added to a multi handle */
+ if(data->multi && data->multi->ssl_seeded)
return CURLE_OK;
if(rand_enough()) {
/* OpenSSL 1.1.0+ will return here */
- ssl_seeded = TRUE;
+ if(data->multi)
+ data->multi->ssl_seeded = TRUE;
return CURLE_OK;
}
@@ -518,7 +517,7 @@ static CURLcode ossl_seed(struct Curl_easy *data)
return CURLE_OK;
}
- infof(data, "libcurl is now using a weak random seed!\n");
+ infof(data, "libcurl is now using a weak random seed!");
return (rand_enough() ? CURLE_OK :
CURLE_SSL_CONNECT_ERROR /* confusing error code */);
}
@@ -1193,7 +1192,7 @@ static int ossl_init(void)
CONF_MFLAGS_IGNORE_MISSING_FILE);
#endif
- /* Lets get nice error messages */
+ /* Let's get nice error messages */
SSL_load_error_strings();
/* Init the global ciphers and digests */
@@ -1354,7 +1353,7 @@ static CURLcode ossl_set_engine_default(struct Curl_easy *data)
#ifdef USE_OPENSSL_ENGINE
if(data->state.engine) {
if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
- infof(data, "set default crypto engine '%s'\n",
+ infof(data, "set default crypto engine '%s'",
ENGINE_get_id(data->state.engine));
}
else {
@@ -1400,7 +1399,13 @@ static void ossl_closeone(struct Curl_easy *data,
{
struct ssl_backend_data *backend = connssl->backend;
if(backend->handle) {
+ char buf[32];
set_logger(conn, data);
+
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
+
(void)SSL_shutdown(backend->handle);
SSL_set_connect_state(backend->handle);
@@ -1442,6 +1447,7 @@ static int ossl_shutdown(struct Curl_easy *data,
int err;
bool done = FALSE;
struct ssl_backend_data *backend = connssl->backend;
+ int loop = 10;
#ifndef CURL_DISABLE_FTP
/* This has only been tested on the proftpd server, and the mod_tls code
@@ -1455,7 +1461,7 @@ static int ossl_shutdown(struct Curl_easy *data,
if(backend->handle) {
buffsize = (int)sizeof(buf);
- while(!done) {
+ while(!done && loop--) {
int what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
@@ -1475,11 +1481,11 @@ static int ossl_shutdown(struct Curl_easy *data,
break;
case SSL_ERROR_WANT_READ:
/* there's data pending, re-invoke SSL_read() */
- infof(data, "SSL_ERROR_WANT_READ\n");
+ infof(data, "SSL_ERROR_WANT_READ");
break;
case SSL_ERROR_WANT_WRITE:
/* SSL wants a write. Really odd. Let's bail out. */
- infof(data, "SSL_ERROR_WANT_WRITE\n");
+ infof(data, "SSL_ERROR_WANT_WRITE");
done = TRUE;
break;
default:
@@ -1511,14 +1517,14 @@ static int ossl_shutdown(struct Curl_easy *data,
#ifdef HAVE_SSL_GET_SHUTDOWN
switch(SSL_get_shutdown(backend->handle)) {
case SSL_SENT_SHUTDOWN:
- infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
+ infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN");
break;
case SSL_RECEIVED_SHUTDOWN:
- infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN\n");
+ infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN");
break;
case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN:
infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|"
- "SSL_RECEIVED__SHUTDOWN\n");
+ "SSL_RECEIVED__SHUTDOWN");
break;
}
#endif
@@ -1585,7 +1591,7 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
if(Curl_cert_hostcheck(match_pattern2, hostname)) {
res = TRUE;
infof(data,
- " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ " subjectAltName: host \"%s\" matched cert's \"%s\"",
dispname, match_pattern2);
}
}
@@ -1604,7 +1610,7 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
(void)data;
#endif
if(Curl_cert_hostcheck(match_pattern, hostname)) {
- infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"",
dispname, match_pattern);
return TRUE;
}
@@ -1724,7 +1730,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
ipmatched = TRUE;
infof(data,
- " subjectAltName: host \"%s\" matched cert's IP address!\n",
+ " subjectAltName: host \"%s\" matched cert's IP address!",
dispname);
}
break;
@@ -1741,7 +1747,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s\n", dispname);
+ infof(data, " subjectAltName does not match %s", dispname);
failf(data, "SSL: no alternative certificate subject name matches "
"target host name '%s'", dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
@@ -1763,7 +1769,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* we have the name entry and we will now convert this to a string
that we can use for comparison. Doing this we support BMPstring,
- UTF8 etc. */
+ UTF8, etc. */
if(i >= 0) {
ASN1_STRING *tmp =
@@ -1823,7 +1829,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
- infof(data, " common name: %s (matched)\n", peer_CN);
+ infof(data, " common name: %s (matched)", peer_CN);
}
if(peer_CN)
OPENSSL_free(peer_CN);
@@ -1959,7 +1965,7 @@ static CURLcode verifystatus(struct Curl_easy *data,
goto end;
}
- infof(data, "SSL certificate status: %s (%d)\n",
+ infof(data, "SSL certificate status: %s (%d)",
OCSP_cert_status_str(cert_status), cert_status);
switch(cert_status) {
@@ -2054,6 +2060,10 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
case SSL3_MT_ENCRYPTED_EXTENSIONS:
return "Encrypted Extensions";
#endif
+#ifdef SSL3_MT_SUPPLEMENTAL_DATA
+ case SSL3_MT_SUPPLEMENTAL_DATA:
+ return "Supplemental data";
+#endif
#ifdef SSL3_MT_END_OF_EARLY_DATA
case SSL3_MT_END_OF_EARLY_DATA:
return "End of early data";
@@ -2152,7 +2162,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
/* Log progress for interesting records only (like Handshake or Alert), skip
* all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
- * For TLS 1.3, skip notification of the decrypted inner Content Type.
+ * For TLS 1.3, skip notification of the decrypted inner Content-Type.
*/
if(ssl_ver
#ifdef SSL3_RT_INNER_CONTENT_TYPE
@@ -2263,7 +2273,7 @@ select_next_proto_cb(SSL *ssl,
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2 &&
!select_next_protocol(out, outlen, in, inlen, ALPN_H2, ALPN_H2_LENGTH)) {
- infof(data, "NPN, negotiated HTTP2 (%s)\n", ALPN_H2);
+ infof(data, "NPN, negotiated HTTP2 (%s)", ALPN_H2);
conn->negnpn = CURL_HTTP_VERSION_2;
return SSL_TLSEXT_ERR_OK;
}
@@ -2271,12 +2281,12 @@ select_next_proto_cb(SSL *ssl,
if(!select_next_protocol(out, outlen, in, inlen, ALPN_HTTP_1_1,
ALPN_HTTP_1_1_LENGTH)) {
- infof(data, "NPN, negotiated HTTP1.1\n");
+ infof(data, "NPN, negotiated HTTP1.1");
conn->negnpn = CURL_HTTP_VERSION_1_1;
return SSL_TLSEXT_ERR_OK;
}
- infof(data, "NPN, no overlap, use HTTP1.1\n");
+ infof(data, "NPN, no overlap, use HTTP1.1");
*out = (unsigned char *)ALPN_HTTP_1_1;
*outlen = ALPN_HTTP_1_1_LENGTH;
conn->negnpn = CURL_HTTP_VERSION_1_1;
@@ -2293,7 +2303,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
long curl_ssl_version_min = SSL_CONN_CONFIG(version);
long curl_ssl_version_max;
- /* convert cURL min SSL version option to OpenSSL constant */
+ /* convert curl min SSL version option to OpenSSL constant */
#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
uint16_t ossl_ssl_version_min = 0;
uint16_t ossl_ssl_version_max = 0;
@@ -2323,7 +2333,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
We don't want to pass 0 to SSL_CTX_set_min_proto_version as
it would enable all versions down to the lowest supported by
the library.
- So we skip this, and stay with the OS default
+ So we skip this, and stay with the library default
*/
if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) {
if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) {
@@ -2334,7 +2344,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
/* ... then, TLS max version */
curl_ssl_version_max = SSL_CONN_CONFIG(version_max);
- /* convert cURL max SSL version option to OpenSSL constant */
+ /* convert curl max SSL version option to OpenSSL constant */
switch(curl_ssl_version_max) {
case CURL_SSLVERSION_MAX_TLSv1_0:
ossl_ssl_version_max = TLS1_VERSION;
@@ -2493,7 +2503,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
&old_ssl_sessionid, NULL, sockindex));
if(incache) {
if(old_ssl_sessionid != ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
+ infof(data, "old SSL session ID is stale, removing");
Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
@@ -2517,7 +2527,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
const struct curl_blob *ca_info_blob)
{
- /* these need freed at the end */
+ /* these need to be freed at the end */
BIO *cbio = NULL;
STACK_OF(X509_INFO) *inf = NULL;
@@ -2652,8 +2662,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if(backend->ctx)
- SSL_CTX_free(backend->ctx);
+ DEBUGASSERT(!backend->ctx);
backend->ctx = SSL_CTX_new(req_method);
if(!backend->ctx) {
@@ -2675,23 +2684,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
#endif
- /* OpenSSL contains code to work-around lots of bugs and flaws in various
+ /* OpenSSL contains code to work around lots of bugs and flaws in various
SSL-implementations. SSL_CTX_set_options() is used to enabled those
work-arounds. The man page for this option states that SSL_OP_ALL enables
all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
enable the bug workaround options if compatibility with somewhat broken
implementations is desired."
- The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
+ The "-no_ticket" option was introduced in OpenSSL 0.9.8j. It's a flag to
disable "rfc4507bis session ticket support". rfc4507bis was later turned
into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077
The enabled extension concerns the session management. I wonder how often
- libcurl stops a connection and then resumes a TLS session. also, sending
- the session data is some overhead. .I suggest that you just use your
+ libcurl stops a connection and then resumes a TLS session. Also, sending
+ the session data is some overhead. I suggest that you just use your
proposed patch (which explicitly disables TICKET).
- If someone writes an application with libcurl and openssl who wants to
+ If someone writes an application with libcurl and OpenSSL who wants to
enable the feature, one can do this in the SSL callback.
SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
@@ -2727,7 +2736,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
- /* unless the user explicitly ask to allow the protocol vulnerability we
+ /* unless the user explicitly asks to allow the protocol vulnerability we
use the work-around */
if(!SSL_SET_OPTION(enable_beast))
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
@@ -2787,14 +2796,14 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
memcpy(&protocols[cur], ALPN_H2, ALPN_H2_LENGTH);
cur += ALPN_H2_LENGTH;
- infof(data, "ALPN, offering %s\n", ALPN_H2);
+ infof(data, "ALPN, offering %s", ALPN_H2);
}
#endif
protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
/* expects length prefixed preference ordered list of protocols in wire
* format
@@ -2826,7 +2835,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
}
- infof(data, "Cipher selection: %s\n", ciphers);
+ infof(data, "Cipher selection: %s", ciphers);
}
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
@@ -2837,7 +2846,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
return CURLE_SSL_CIPHER;
}
- infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13);
+ infof(data, "TLS 1.3 cipher selection: %s", ciphers13);
}
}
#endif
@@ -2863,7 +2872,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
if(ssl_authtype == CURL_TLSAUTH_SRP) {
char * const ssl_username = SSL_SET_OPTION(username);
- infof(data, "Using TLS-SRP username: %s\n", ssl_username);
+ infof(data, "Using TLS-SRP username: %s", ssl_username);
if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) {
failf(data, "Unable to set SRP user name");
@@ -2874,7 +2883,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
if(!SSL_CONN_CONFIG(cipher_list)) {
- infof(data, "Setting cipher list SRP\n");
+ infof(data, "Setting cipher list SRP");
if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) {
failf(data, "failed setting SRP cipher list");
@@ -2927,7 +2936,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
NULL, cert_name, sizeof(cert_name))) {
strcpy(cert_name, "Unknown");
}
- infof(data, "SSL: Checking cert \"%s\"\n", cert_name);
+ infof(data, "SSL: Checking cert %s\"\n", cert_name);
#endif
encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
@@ -3009,7 +3018,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
OpenSSL. */
if(X509_STORE_add_cert(store, x509) == 1) {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- infof(data, "SSL: Imported cert \"%s\"\n", cert_name);
+ infof(data, "SSL: Imported cert \"%s\"", cert_name);
#endif
imported_native_ca = true;
}
@@ -3024,9 +3033,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return result;
}
if(imported_native_ca)
- infof(data, "successfully imported windows ca store\n");
+ infof(data, "successfully imported Windows CA store");
else
- infof(data, "error importing windows ca store, continuing anyway\n");
+ infof(data, "error importing Windows CA store, continuing anyway");
}
#endif
@@ -3038,8 +3047,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "error importing CA certificate blob");
return result;
}
- /* Only warning if no certificate verification is required. */
- infof(data, "error importing CA certificate blob, continuing anyway\n");
+ /* Only warn if no certificate verification is required. */
+ infof(data, "error importing CA certificate blob, continuing anyway");
}
}
@@ -3053,10 +3062,10 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "error setting certificate file: %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
}
- /* Continue with a warning if no certificate verif is required. */
- infof(data, "error setting certificate file, continuing anyway\n");
+ /* Continue with warning if certificate verification isn't required. */
+ infof(data, "error setting certificate file, continuing anyway");
}
- infof(data, " CAfile: %s\n", ssl_cafile);
+ infof(data, " CAfile: %s", ssl_cafile);
}
if(ssl_capath) {
if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
@@ -3065,16 +3074,16 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "error setting certificate path: %s", ssl_capath);
return CURLE_SSL_CACERT_BADFILE;
}
- /* Continue with a warning if no certificate verif is required. */
- infof(data, "error setting certificate path, continuing anyway\n");
+ /* Continue with warning if certificate verification isn't required. */
+ infof(data, "error setting certificate path, continuing anyway");
}
- infof(data, " CApath: %s\n", ssl_capath);
+ infof(data, " CApath: %s", ssl_capath);
}
}
#else
if(ssl_cafile || ssl_capath) {
/* tell SSL where to find CA certificates that are used to verify
- the servers certificate. */
+ the server's certificate. */
if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
@@ -3087,14 +3096,14 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
/* Just continue with a warning if no strict certificate verification
is required. */
infof(data, "error setting certificate verify locations,"
- " continuing anyway:\n");
+ " continuing anyway:");
}
else {
/* Everything is fine. */
- infof(data, "successfully set certificate verify locations:\n");
+ infof(data, "successfully set certificate verify locations:");
}
- infof(data, " CAfile: %s\n", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s\n", ssl_capath ? ssl_capath : "none");
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
}
#endif
@@ -3102,13 +3111,13 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
if(verifypeer &&
!ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
/* verifying the peer without any CA certificates won't
- work so use openssl's built in default as fallback */
+ work so use openssl's built-in default as fallback */
SSL_CTX_set_default_verify_paths(backend->ctx);
}
#endif
if(ssl_crlfile) {
- /* tell SSL where to find CRL file that is used to check certificate
+ /* tell OpenSSL where to find CRL file that is used to check certificate
* revocation */
lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
X509_LOOKUP_file());
@@ -3118,11 +3127,11 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CRL_BADFILE;
}
/* Everything is fine. */
- infof(data, "successfully load CRL file:\n");
+ infof(data, "successfully loaded CRL file:");
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
- infof(data, " CRLfile: %s\n", ssl_crlfile);
+ infof(data, " CRLfile: %s", ssl_crlfile);
}
if(verifypeer) {
@@ -3144,7 +3153,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
only, instead of needing the whole chain.
Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
- cannot do partial chains with CRL check.
+ cannot do partial chains with a CRL check.
*/
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_PARTIAL_CHAIN);
@@ -3152,7 +3161,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
}
- /* SSL always tries to verify the peer, this only says whether it should
+ /* OpenSSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
@@ -3167,7 +3176,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
/* Enable the session cache because it's a prerequisite for the "new session"
- * callback. Use the "external storage" mode to avoid that OpenSSL creates
+ * callback. Use the "external storage" mode to prevent OpenSSL from creating
* an internal session cache.
*/
SSL_CTX_set_session_cache_mode(backend->ctx,
@@ -3186,7 +3195,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
}
- /* Lets make an SSL structure */
+ /* Let's make an SSL structure */
if(backend->handle)
SSL_free(backend->handle);
backend->handle = SSL_new(backend->ctx);
@@ -3226,7 +3235,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
data->state.buffer[nlen] = 0;
if(!SSL_set_tlsext_host_name(backend->handle, data->state.buffer))
infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
+ "TLS extension");
}
#endif
@@ -3244,7 +3253,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof(data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
@@ -3326,7 +3335,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
/* the connection failed, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_2;
- /* Get the earliest error code from the thread's error queue and removes
+ /* Get the earliest error code from the thread's error queue and remove
the entry. */
errdetail = ERR_get_error();
@@ -3355,7 +3364,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
!defined(LIBRESSL_VERSION_NUMBER) && \
!defined(OPENSSL_IS_BORINGSSL))
/* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
- OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */
+ OpenSSL version above v1.1.1, not LibreSSL nor BoringSSL */
else if((lib == ERR_LIB_SSL) &&
(reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
/* If client certificate is required, communicate the
@@ -3372,7 +3381,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
/* detail is already set to the SSL error above */
/* If we e.g. use SSLv2 request-method and the server doesn't like us
- * (RST connection etc.), OpenSSL gives no explanation whatsoever and
+ * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
@@ -3395,11 +3404,11 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
}
}
else {
- /* we have been connected fine, we're not waiting for anything else. */
+ /* we connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
/* Informational message */
- infof(data, "SSL connection using %s / %s\n",
+ infof(data, "SSL connection using %s / %s",
SSL_get_version(backend->handle),
SSL_get_cipher(backend->handle));
@@ -3412,7 +3421,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
unsigned int len;
SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len);
if(len) {
- infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
+ infof(data, "ALPN, server accepted to use %.*s", len, neg_protocol);
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH &&
@@ -3427,7 +3436,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
}
}
else
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
@@ -3637,7 +3646,7 @@ static CURLcode get_cert_chain(struct Curl_easy *data,
pubkey = X509_get_pubkey(x);
if(!pubkey)
- infof(data, " Unable to load public key\n");
+ infof(data, " Unable to load public key");
else {
int pktype;
#ifdef HAVE_OPAQUE_EVP_PKEY
@@ -3814,7 +3823,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
}
/*
- * Get the server cert, verify it and show it etc, only call failf() if the
+ * Get the server cert, verify it and show it, etc., only call failf() if the
* 'strict' argument is TRUE as otherwise all this is for informational
* purposes only!
*
@@ -3851,23 +3860,23 @@ static CURLcode servercert(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
}
- infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
+ infof(data, "%s certificate:", SSL_IS_PROXY() ? "Proxy" : "Server");
rc = x509_name_oneline(X509_get_subject_name(backend->server_cert),
buffer, sizeof(buffer));
- infof(data, " subject: %s\n", rc?"[NONE]":buffer);
+ infof(data, " subject: %s", rc?"[NONE]":buffer);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
{
long len;
ASN1_TIME_print(mem, X509_get0_notBefore(backend->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " start date: %.*s\n", len, ptr);
+ infof(data, " start date: %.*s", (int)len, ptr);
(void)BIO_reset(mem);
ASN1_TIME_print(mem, X509_get0_notAfter(backend->server_cert));
len = BIO_get_mem_data(mem, (char **) &ptr);
- infof(data, " expire date: %.*s\n", len, ptr);
+ infof(data, " expire date: %.*s", (int)len, ptr);
(void)BIO_reset(mem);
}
#endif
@@ -3891,16 +3900,16 @@ static CURLcode servercert(struct Curl_easy *data,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
- infof(data, " issuer: %s\n", buffer);
+ infof(data, " issuer: %s", buffer);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(SSL_SET_OPTION(issuercert) || SSL_SET_OPTION(issuercert_blob)) {
- if(SSL_SET_OPTION(issuercert_blob))
- fp = BIO_new_mem_buf(SSL_SET_OPTION(issuercert_blob)->data,
- (int)SSL_SET_OPTION(issuercert_blob)->len);
+ if(SSL_CONN_CONFIG(issuercert) || SSL_CONN_CONFIG(issuercert_blob)) {
+ if(SSL_CONN_CONFIG(issuercert_blob))
+ fp = BIO_new_mem_buf(SSL_CONN_CONFIG(issuercert_blob)->data,
+ (int)SSL_CONN_CONFIG(issuercert_blob)->len);
else {
fp = BIO_new(BIO_s_file());
if(!fp) {
@@ -3914,10 +3923,10 @@ static CURLcode servercert(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
- if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
+ if(BIO_read_filename(fp, SSL_CONN_CONFIG(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -3929,7 +3938,7 @@ static CURLcode servercert(struct Curl_easy *data,
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3940,7 +3949,7 @@ static CURLcode servercert(struct Curl_easy *data,
if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
- SSL_SET_OPTION(issuercert));
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
X509_free(backend->server_cert);
@@ -3948,8 +3957,8 @@ static CURLcode servercert(struct Curl_easy *data,
return CURLE_SSL_ISSUER_ERROR;
}
- infof(data, " SSL certificate issuer check ok (%s)\n",
- SSL_SET_OPTION(issuercert));
+ infof(data, " SSL certificate issuer check ok (%s)",
+ SSL_CONN_CONFIG(issuercert));
BIO_free(fp);
X509_free(issuer);
}
@@ -3967,11 +3976,11 @@ static CURLcode servercert(struct Curl_easy *data,
}
else
infof(data, " SSL certificate verify result: %s (%ld),"
- " continuing anyway.\n",
+ " continuing anyway.",
X509_verify_cert_error_string(lerr), lerr);
}
else
- infof(data, " SSL certificate verify ok.\n");
+ infof(data, " SSL certificate verify ok.");
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
@@ -4015,7 +4024,7 @@ static CURLcode ossl_connect_step3(struct Curl_easy *data,
/*
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
- * verify the peer ignore faults and failures from the server cert
+ * verify the peer, ignore faults and failures from the server cert
* operations.
*/
@@ -4053,7 +4062,7 @@ static CURLcode ossl_connect_common(struct Curl_easy *data,
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
- /* no need to continue if time already is up */
+ /* no need to continue if time is already up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
@@ -4244,7 +4253,7 @@ static ssize_t ossl_send(struct Curl_easy *data,
#endif
) {
char ver[120];
- ossl_version(ver, 120);
+ (void)ossl_version(ver, sizeof(ver));
failf(data, "Error: %s does not support double SSL tunneling.", ver);
}
else
@@ -4534,9 +4543,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data,
return;
if(SSL_SET_OPTION(primary.sessionid)) {
- bool isproxy = FALSE;
- bool incache;
- void *old_ssl_sessionid = NULL;
int data_idx = ossl_get_ssl_data_index();
int connectdata_idx = ossl_get_ssl_conn_index();
int sockindex_idx = ossl_get_ssl_sockindex_index();
@@ -4544,9 +4550,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data,
if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
proxy_idx >= 0) {
- /* Invalidate the session cache entry, if any */
- isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE;
-
/* Disable references to data in "new session" callback to avoid
* accessing a stale pointer. */
SSL_set_ex_data(backend->handle, data_idx, NULL);
@@ -4554,13 +4557,6 @@ static void ossl_disassociate_connection(struct Curl_easy *data,
SSL_set_ex_data(backend->handle, sockindex_idx, NULL);
SSL_set_ex_data(backend->handle, proxy_idx, NULL);
}
-
- Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
- &old_ssl_sessionid, NULL, sockindex));
- if(incache)
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
- Curl_ssl_sessionid_unlock(data);
}
}
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
index d5247f936..2ac97ce28 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.c
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -34,7 +34,7 @@
#include "sendf.h"
#include "vtls.h"
#include "select.h"
-
+#include "strerror.h"
#include "multiif.h"
struct ssl_backend_data
@@ -73,7 +73,7 @@ cr_connect(struct Curl_easy *data UNUSED_PARAM,
struct connectdata *conn UNUSED_PARAM,
int sockindex UNUSED_PARAM)
{
- infof(data, "rustls_connect: unimplemented\n");
+ infof(data, "rustls_connect: unimplemented");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -129,10 +129,12 @@ cr_recv(struct Curl_easy *data, int sockindex,
io_error = rustls_connection_read_tls(rconn, read_cb,
&conn->sock[sockindex], &tls_bytes_read);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "sread: EAGAIN or EWOULDBLOCK\n");
+ infof(data, "sread: EAGAIN or EWOULDBLOCK");
}
else if(io_error) {
- failf(data, "reading from socket: %s", strerror(io_error));
+ char buffer[STRERROR_LEN];
+ failf(data, "reading from socket: %s",
+ Curl_strerror(io_error, buffer, sizeof(buffer)));
*err = CURLE_READ_ERROR;
return -1;
}
@@ -142,7 +144,7 @@ cr_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- infof(data, "cr_recv read %ld bytes from the network\n", tls_bytes_read);
+ infof(data, "cr_recv read %ld bytes from the network", tls_bytes_read);
rresult = rustls_connection_process_new_packets(rconn);
if(rresult != RUSTLS_RESULT_OK) {
@@ -173,12 +175,12 @@ cr_recv(struct Curl_easy *data, int sockindex,
available data has been read." If we bring in more ciphertext with
read_tls, more plaintext will become available. So don't tell curl
this is an EOF. Instead, say "come back later." */
- infof(data, "cr_recv got 0 bytes of plaintext\n");
+ infof(data, "cr_recv got 0 bytes of plaintext");
backend->data_pending = FALSE;
break;
}
else {
- infof(data, "cr_recv copied out %ld bytes of plaintext\n", n);
+ infof(data, "cr_recv copied out %ld bytes of plaintext", n);
plain_bytes_copied += n;
}
}
@@ -218,7 +220,7 @@ cr_send(struct Curl_easy *data, int sockindex,
rustls_result rresult;
rustls_io_result io_error;
- infof(data, "cr_send %ld bytes of plaintext\n", plainlen);
+ infof(data, "cr_send %ld bytes of plaintext", plainlen);
if(plainlen > 0) {
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
@@ -239,12 +241,14 @@ cr_send(struct Curl_easy *data, int sockindex,
io_error = rustls_connection_write_tls(rconn, write_cb,
&conn->sock[sockindex], &tlswritten);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "swrite: EAGAIN after %ld bytes\n", tlswritten_total);
+ infof(data, "swrite: EAGAIN after %ld bytes", tlswritten_total);
*err = CURLE_AGAIN;
return -1;
}
else if(io_error) {
- failf(data, "writing to socket: %s", strerror(io_error));
+ char buffer[STRERROR_LEN];
+ failf(data, "writing to socket: %s",
+ Curl_strerror(io_error, buffer, sizeof(buffer)));
*err = CURLE_WRITE_ERROR;
return -1;
}
@@ -253,7 +257,7 @@ cr_send(struct Curl_easy *data, int sockindex,
*err = CURLE_WRITE_ERROR;
return -1;
}
- infof(data, "cr_send wrote %ld bytes to network\n", tlswritten);
+ infof(data, "cr_send wrote %ld bytes to network", tlswritten);
tlswritten_total += tlswritten;
}
@@ -304,10 +308,10 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
config_builder = rustls_client_config_builder_new();
#ifdef USE_HTTP2
- infof(data, "offering ALPN for HTTP/1.1 and HTTP/2\n");
+ infof(data, "offering ALPN for HTTP/1.1 and HTTP/2");
rustls_client_config_builder_set_protocols(config_builder, alpn, 2);
#else
- infof(data, "offering ALPN for HTTP/1.1 only\n");
+ infof(data, "offering ALPN for HTTP/1.1 only");
rustls_client_config_builder_set_protocols(config_builder, alpn, 1);
#endif
if(!verifypeer) {
@@ -332,15 +336,6 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CACERT_BADFILE;
}
}
- else {
- result = rustls_client_config_builder_load_native_roots(config_builder);
- if(result != RUSTLS_RESULT_OK) {
- failf(data, "failed to load trusted certificates");
- rustls_client_config_free(
- rustls_client_config_builder_build(config_builder));
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
backend->config = rustls_client_config_builder_build(config_builder);
DEBUGASSERT(rconn == NULL);
@@ -364,24 +359,24 @@ cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
rustls_connection_get_alpn_protocol(rconn, &protocol, &len);
if(NULL == protocol) {
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
return;
}
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
- infof(data, "ALPN, negotiated h2\n");
+ infof(data, "ALPN, negotiated h2");
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
- infof(data, "ALPN, negotiated http/1.1\n");
+ infof(data, "ALPN, negotiated http/1.1");
conn->negnpn = CURL_HTTP_VERSION_1_1;
}
else {
- infof(data, "ALPN, negotiated an unrecognized protocol\n");
+ infof(data, "ALPN, negotiated an unrecognized protocol");
}
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
@@ -424,7 +419,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
* once the handshake is done.
*/
if(!rustls_connection_is_handshaking(rconn)) {
- infof(data, "Done handshaking\n");
+ infof(data, "Done handshaking");
/* Done with the handshake. Set up callbacks to send/receive data. */
connssl->state = ssl_connection_complete;
@@ -449,22 +444,19 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
return CURLE_SSL_CONNECT_ERROR;
}
if(0 == what) {
- infof(data, "Curl_socket_check: %s would block\n",
- wants_read&&wants_write ?
- "writing and reading" :
- wants_write ?
- "writing" :
- "reading");
+ infof(data, "Curl_socket_check: %s would block",
+ wants_read&&wants_write ? "writing and reading" :
+ wants_write ? "writing" : "reading");
*done = FALSE;
return CURLE_OK;
}
/* socket is readable or writable */
if(wants_write) {
- infof(data, "rustls_connection wants us to write_tls.\n");
+ infof(data, "rustls_connection wants us to write_tls.");
cr_send(data, sockindex, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) {
- infof(data, "writing would block\n");
+ infof(data, "writing would block");
/* fall through */
}
else if(tmperr != CURLE_OK) {
@@ -473,11 +465,11 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
}
if(wants_read) {
- infof(data, "rustls_connection wants us to read_tls.\n");
+ infof(data, "rustls_connection wants us to read_tls.");
cr_recv(data, sockindex, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) {
- infof(data, "reading would block\n");
+ infof(data, "reading would block");
/* fall through */
}
else if(tmperr != CURLE_OK) {
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 3286a9e9f..722a937c4 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -141,6 +141,12 @@
# define CALG_SHA_256 0x0000800c
#endif
+/* Work around typo in classic MinGW's w32api up to version 5.0,
+ see https://osdn.net/projects/mingw/ticket/38391 */
+#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH)
+#define ALG_CLASS_DHASH ALG_CLASS_HASH
+#endif
+
#define BACKEND connssl->backend
static Curl_recv schannel_recv;
@@ -279,13 +285,7 @@ get_alg_id_by_name(char *name)
#ifdef CALG_HMAC
CIPHEROPTION(CALG_HMAC);
#endif
-#if !defined(__W32API_MAJOR_VERSION) || \
- !defined(__W32API_MINOR_VERSION) || \
- defined(__MINGW64_VERSION_MAJOR) || \
- (__W32API_MAJOR_VERSION > 5) || \
- ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
- /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
- see https://osdn.net/projects/mingw/ticket/38391 */
+#ifdef CALG_TLS1PRF
CIPHEROPTION(CALG_TLS1PRF);
#endif
#ifdef CALG_HASH_REPLACE_OWF
@@ -372,23 +372,23 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
store_name_len = sep - path;
- if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0)
+ if(_tcsncmp(path, TEXT("CurrentUser"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_CURRENT_USER;
- else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0)
+ else if(_tcsncmp(path, TEXT("LocalMachine"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE;
- else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0)
+ else if(_tcsncmp(path, TEXT("CurrentService"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE;
- else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0)
+ else if(_tcsncmp(path, TEXT("Services"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_SERVICES;
- else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0)
+ else if(_tcsncmp(path, TEXT("Users"), store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_USERS;
- else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"),
+ else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"),
store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
- else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"),
+ else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"),
store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
- else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"),
+ else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"),
store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else
@@ -413,6 +413,341 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
return CURLE_OK;
}
#endif
+static CURLcode
+schannel_acquire_credential_handle(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ SCHANNEL_CRED schannel_cred;
+ PCCERT_CONTEXT client_certs[1] = { NULL };
+ SECURITY_STATUS sspi_status = SEC_E_OK;
+ CURLcode result;
+
+ /* setup Schannel API options */
+ memset(&schannel_cred, 0, sizeof(schannel_cred));
+ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
+
+ if(conn->ssl_config.verifypeer) {
+#ifdef HAS_MANUAL_VERIFY_API
+ if(BACKEND->use_manual_cred_validation)
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ else
+#endif
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+
+ if(SSL_SET_OPTION(no_revoke)) {
+ schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+
+ DEBUGF(infof(data, "schannel: disabled server certificate revocation "
+ "checks"));
+ }
+ else if(SSL_SET_OPTION(revoke_best_effort)) {
+ schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
+
+ DEBUGF(infof(data, "schannel: ignore revocation offline errors"));
+ }
+ else {
+ schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
+
+ DEBUGF(infof(data,
+ "schannel: checking server certificate revocation"));
+ }
+ }
+ else {
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+ DEBUGF(infof(data,
+ "schannel: disabled server cert revocation checks"));
+ }
+
+ if(!conn->ssl_config.verifyhost) {
+ schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
+ DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from "
+ "comparing the supplied target name with the subject "
+ "names in server certificates."));
+ }
+
+ if(!SSL_SET_OPTION(auto_client_cert)) {
+ schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
+ schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
+ infof(data, "schannel: disabled automatic use of client certificate");
+ }
+ else
+ infof(data, "schannel: enabled automatic use of client certificate");
+
+ switch(conn->ssl_config.version) {
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ case CURL_SSLVERSION_TLSv1_3:
+ {
+ result = set_ssl_version_min_max(&schannel_cred, data, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
+ case CURL_SSLVERSION_SSLv3:
+ case CURL_SSLVERSION_SSLv2:
+ failf(data, "SSL versions not supported");
+ return CURLE_NOT_BUILT_IN;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(SSL_CONN_CONFIG(cipher_list)) {
+ result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
+ BACKEND->algIds);
+ if(CURLE_OK != result) {
+ failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+ return result;
+ }
+ }
+
+
+#ifdef HAS_CLIENT_CERT_PATH
+ /* client certificate */
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
+ DWORD cert_store_name = 0;
+ TCHAR *cert_store_path = NULL;
+ TCHAR *cert_thumbprint_str = NULL;
+ CRYPT_HASH_BLOB cert_thumbprint;
+ BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
+ HCERTSTORE cert_store = NULL;
+ FILE *fInCert = NULL;
+ void *certdata = NULL;
+ size_t certsize = 0;
+ bool blob = data->set.ssl.primary.cert_blob != NULL;
+ TCHAR *cert_path = NULL;
+ if(blob) {
+ certdata = data->set.ssl.primary.cert_blob->data;
+ certsize = data->set.ssl.primary.cert_blob->len;
+ }
+ else {
+ cert_path = curlx_convert_UTF8_to_tchar(
+ data->set.ssl.primary.clientcert);
+ if(!cert_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = get_cert_location(cert_path, &cert_store_name,
+ &cert_store_path, &cert_thumbprint_str);
+
+ if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
+ fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
+
+ if(result && !fInCert) {
+ failf(data, "schannel: Failed to get certificate location"
+ " or file for %s",
+ data->set.ssl.primary.clientcert);
+ curlx_unicodefree(cert_path);
+ return result;
+ }
+ }
+
+ if((fInCert || blob) && (data->set.ssl.cert_type) &&
+ (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
+ failf(data, "schannel: certificate format compatibility error "
+ " for %s",
+ blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
+ curlx_unicodefree(cert_path);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+
+ if(fInCert || blob) {
+ /* Reading a .P12 or .pfx file, like the example at bottom of
+ https://social.msdn.microsoft.com/Forums/windowsdesktop/
+ en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
+ */
+ CRYPT_DATA_BLOB datablob;
+ WCHAR* pszPassword;
+ size_t pwd_len = 0;
+ int str_w_len = 0;
+ const char *cert_showfilename_error = blob ?
+ "(memory blob)" : data->set.ssl.primary.clientcert;
+ curlx_unicodefree(cert_path);
+ if(fInCert) {
+ long cert_tell = 0;
+ bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ cert_tell = ftell(fInCert);
+ if(cert_tell < 0)
+ continue_reading = FALSE;
+ else
+ certsize = (size_t)cert_tell;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(certsize + 1);
+ if((!certdata) ||
+ ((int) fread(certdata, certsize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ fclose(fInCert);
+ if(!continue_reading) {
+ failf(data, "schannel: Failed to read cert file %s",
+ data->set.ssl.primary.clientcert);
+ free(certdata);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+
+ /* Convert key-pair data to the in-memory certificate store */
+ datablob.pbData = (BYTE*)certdata;
+ datablob.cbData = (DWORD)certsize;
+
+ if(data->set.ssl.key_passwd != NULL)
+ pwd_len = strlen(data->set.ssl.key_passwd);
+ pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1));
+ if(pszPassword) {
+ if(pwd_len > 0)
+ str_w_len = MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ data->set.ssl.key_passwd, (int)pwd_len,
+ pszPassword, (int)(pwd_len + 1));
+
+ if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
+ pszPassword[str_w_len] = 0;
+ else
+ pszPassword[0] = 0;
+
+ cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+ free(pszPassword);
+ }
+ if(!blob)
+ free(certdata);
+ if(!cert_store) {
+ DWORD errorcode = GetLastError();
+ if(errorcode == ERROR_INVALID_PASSWORD)
+ failf(data, "schannel: Failed to import cert file %s, "
+ "password is bad",
+ cert_showfilename_error);
+ else
+ failf(data, "schannel: Failed to import cert file %s, "
+ "last error is 0x%x",
+ cert_showfilename_error, errorcode);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+
+ client_certs[0] = CertFindCertificateInStore(
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_ANY, NULL, NULL);
+
+ if(!client_certs[0]) {
+ failf(data, "schannel: Failed to get certificate from file %s"
+ ", last error is 0x%x",
+ cert_showfilename_error, GetLastError());
+ CertCloseStore(cert_store, 0);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+ else {
+ cert_store =
+ CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
+ cert_store_path);
+ if(!cert_store) {
+ failf(data, "schannel: Failed to open cert store %x %s, "
+ "last error is 0x%x",
+ cert_store_name, cert_store_path, GetLastError());
+ free(cert_store_path);
+ curlx_unicodefree(cert_path);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ free(cert_store_path);
+
+ cert_thumbprint.pbData = cert_thumbprint_data;
+ cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
+
+ if(!CryptStringToBinary(cert_thumbprint_str,
+ CERT_THUMBPRINT_STR_LEN,
+ CRYPT_STRING_HEX,
+ cert_thumbprint_data,
+ &cert_thumbprint.cbData,
+ NULL, NULL)) {
+ curlx_unicodefree(cert_path);
+ CertCloseStore(cert_store, 0);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+
+ client_certs[0] = CertFindCertificateInStore(
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_HASH, &cert_thumbprint, NULL);
+
+ curlx_unicodefree(cert_path);
+
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+ else {
+ /* CRYPT_E_NOT_FOUND / E_INVALIDARG */
+ CertCloseStore(cert_store, 0);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ }
+ CertCloseStore(cert_store, 0);
+ }
+#else
+ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
+ failf(data, "schannel: client cert support not built in");
+ return CURLE_NOT_BUILT_IN;
+ }
+#endif
+
+ /* allocate memory for the re-usable credential handle */
+ BACKEND->cred = (struct Curl_schannel_cred *)
+ calloc(1, sizeof(struct Curl_schannel_cred));
+ if(!BACKEND->cred) {
+ failf(data, "schannel: unable to allocate memory");
+
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
+ return CURLE_OUT_OF_MEMORY;
+ }
+ BACKEND->cred->refcount = 1;
+
+ /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
+ */
+ sspi_status =
+ s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
+ SECPKG_CRED_OUTBOUND, NULL,
+ &schannel_cred, NULL, NULL,
+ &BACKEND->cred->cred_handle,
+ &BACKEND->cred->time_stamp);
+
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
+ if(sspi_status != SEC_E_OK) {
+ char buffer[STRERROR_LEN];
+ failf(data, "schannel: AcquireCredentialsHandle failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ Curl_safefree(BACKEND->cred);
+ switch(sspi_status) {
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_SECPKG_NOT_FOUND:
+ case SEC_E_NOT_OWNER:
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ case SEC_E_INTERNAL_ERROR:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
static CURLcode
schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
@@ -427,8 +762,6 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#ifdef HAS_ALPN
unsigned char alpn_buffer[128];
#endif
- SCHANNEL_CRED schannel_cred;
- PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
struct Curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
@@ -440,7 +773,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
char * const hostname = SSL_HOST_NAME();
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
+ "schannel: SSL/TLS connection with %s port %hu (step 1/3)",
hostname, conn->remote_port));
if(curlx_verify_windows_version(5, 1, PLATFORM_WINNT,
@@ -448,7 +781,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
/* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
algorithms that may not be supported by all servers. */
infof(data, "schannel: Windows version is old and may not be able to "
- "connect to some servers due to lack of SNI, algorithms, etc.\n");
+ "connect to some servers due to lack of SNI, algorithms, etc.");
}
#ifdef HAS_ALPN
@@ -503,338 +836,21 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
SSL_IS_PROXY() ? TRUE : FALSE,
(void **)&old_cred, NULL, sockindex)) {
BACKEND->cred = old_cred;
- DEBUGF(infof(data, "schannel: re-using existing credential handle\n"));
+ DEBUGF(infof(data, "schannel: re-using existing credential handle"));
/* increment the reference counter of the credential/session handle */
BACKEND->cred->refcount++;
DEBUGF(infof(data,
- "schannel: incremented credential handle refcount = %d\n",
+ "schannel: incremented credential handle refcount = %d",
BACKEND->cred->refcount));
}
Curl_ssl_sessionid_unlock(data);
}
if(!BACKEND->cred) {
- /* setup Schannel API options */
- memset(&schannel_cred, 0, sizeof(schannel_cred));
- schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
-
- if(conn->ssl_config.verifypeer) {
-#ifdef HAS_MANUAL_VERIFY_API
- if(BACKEND->use_manual_cred_validation)
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
- else
-#endif
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
-
- if(SSL_SET_OPTION(no_revoke)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-
- DEBUGF(infof(data, "schannel: disabled server certificate revocation "
- "checks\n"));
- }
- else if(SSL_SET_OPTION(revoke_best_effort)) {
- schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN;
-
- DEBUGF(infof(data, "schannel: ignore revocation offline errors"));
- }
- else {
- schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
-
- DEBUGF(infof(data,
- "schannel: checking server certificate revocation\n"));
- }
- }
- else {
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
- SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
- DEBUGF(infof(data,
- "schannel: disabled server cert revocation checks\n"));
- }
-
- if(!conn->ssl_config.verifyhost) {
- schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
- DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from "
- "comparing the supplied target name with the subject "
- "names in server certificates.\n"));
- }
-
- if(!SSL_SET_OPTION(auto_client_cert)) {
- schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS;
- schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
- infof(data, "schannel: disabled automatic use of client certificate\n");
- }
- else
- infof(data, "schannel: enabled automatic use of client certificate\n");
-
- switch(conn->ssl_config.version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- {
- result = set_ssl_version_min_max(&schannel_cred, data, conn);
- if(result != CURLE_OK)
- return result;
- break;
- }
- case CURL_SSLVERSION_SSLv3:
- case CURL_SSLVERSION_SSLv2:
- failf(data, "SSL versions not supported");
- return CURLE_NOT_BUILT_IN;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- if(SSL_CONN_CONFIG(cipher_list)) {
- result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
- BACKEND->algIds);
- if(CURLE_OK != result) {
- failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
- return result;
- }
- }
-
-
-#ifdef HAS_CLIENT_CERT_PATH
- /* client certificate */
- if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
- DWORD cert_store_name = 0;
- TCHAR *cert_store_path = NULL;
- TCHAR *cert_thumbprint_str = NULL;
- CRYPT_HASH_BLOB cert_thumbprint;
- BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
- HCERTSTORE cert_store = NULL;
- FILE *fInCert = NULL;
- void *certdata = NULL;
- size_t certsize = 0;
- bool blob = data->set.ssl.primary.cert_blob != NULL;
- TCHAR *cert_path = NULL;
- if(blob) {
- certdata = data->set.ssl.primary.cert_blob->data;
- certsize = data->set.ssl.primary.cert_blob->len;
- }
- else {
- cert_path = curlx_convert_UTF8_to_tchar(
- data->set.ssl.primary.clientcert);
- if(!cert_path)
- return CURLE_OUT_OF_MEMORY;
-
- result = get_cert_location(cert_path, &cert_store_name,
- &cert_store_path, &cert_thumbprint_str);
-
- if(result && (data->set.ssl.primary.clientcert[0]!='\0'))
- fInCert = fopen(data->set.ssl.primary.clientcert, "rb");
-
- if(result && !fInCert) {
- failf(data, "schannel: Failed to get certificate location"
- " or file for %s",
- data->set.ssl.primary.clientcert);
- curlx_unicodefree(cert_path);
- return result;
- }
- }
-
- if((fInCert || blob) && (data->set.ssl.cert_type) &&
- (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
- failf(data, "schannel: certificate format compatibility error "
- " for %s",
- blob ? "(memory blob)" : data->set.ssl.primary.clientcert);
- curlx_unicodefree(cert_path);
- return CURLE_SSL_CERTPROBLEM;
- }
-
- if(fInCert || blob) {
- /* Reading a .P12 or .pfx file, like the example at bottom of
- https://social.msdn.microsoft.com/Forums/windowsdesktop/
- en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
- */
- CRYPT_DATA_BLOB datablob;
- WCHAR* pszPassword;
- size_t pwd_len = 0;
- int str_w_len = 0;
- const char *cert_showfilename_error = blob ?
- "(memory blob)" : data->set.ssl.primary.clientcert;
- curlx_unicodefree(cert_path);
- if(fInCert) {
- long cert_tell = 0;
- bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
- if(continue_reading)
- cert_tell = ftell(fInCert);
- if(cert_tell < 0)
- continue_reading = FALSE;
- else
- certsize = (size_t)cert_tell;
- if(continue_reading)
- continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
- if(continue_reading)
- certdata = malloc(certsize + 1);
- if((!certdata) ||
- ((int) fread(certdata, certsize, 1, fInCert) != 1))
- continue_reading = FALSE;
- fclose(fInCert);
- if(!continue_reading) {
- failf(data, "schannel: Failed to read cert file %s",
- data->set.ssl.primary.clientcert);
- free(certdata);
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- /* Convert key-pair data to the in-memory certificate store */
- datablob.pbData = (BYTE*)certdata;
- datablob.cbData = (DWORD)certsize;
-
- if(data->set.ssl.key_passwd != NULL)
- pwd_len = strlen(data->set.ssl.key_passwd);
- pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1));
- if(pszPassword) {
- if(pwd_len > 0)
- str_w_len = MultiByteToWideChar(CP_UTF8,
- MB_ERR_INVALID_CHARS,
- data->set.ssl.key_passwd, (int)pwd_len,
- pszPassword, (int)(pwd_len + 1));
-
- if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
- pszPassword[str_w_len] = 0;
- else
- pszPassword[0] = 0;
-
- cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
- free(pszPassword);
- }
- if(!blob)
- free(certdata);
- if(!cert_store) {
- DWORD errorcode = GetLastError();
- if(errorcode == ERROR_INVALID_PASSWORD)
- failf(data, "schannel: Failed to import cert file %s, "
- "password is bad",
- cert_showfilename_error);
- else
- failf(data, "schannel: Failed to import cert file %s, "
- "last error is 0x%x",
- cert_showfilename_error, errorcode);
- return CURLE_SSL_CERTPROBLEM;
- }
-
- client_certs[0] = CertFindCertificateInStore(
- cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_ANY, NULL, NULL);
-
- if(!client_certs[0]) {
- failf(data, "schannel: Failed to get certificate from file %s"
- ", last error is 0x%x",
- cert_showfilename_error, GetLastError());
- CertCloseStore(cert_store, 0);
- return CURLE_SSL_CERTPROBLEM;
- }
-
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
- }
- else {
- cert_store =
- CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
- (HCRYPTPROV)NULL,
- CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
- cert_store_path);
- if(!cert_store) {
- failf(data, "schannel: Failed to open cert store %x %s, "
- "last error is 0x%x",
- cert_store_name, cert_store_path, GetLastError());
- free(cert_store_path);
- curlx_unicodefree(cert_path);
- return CURLE_SSL_CERTPROBLEM;
- }
- free(cert_store_path);
-
- cert_thumbprint.pbData = cert_thumbprint_data;
- cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
-
- if(!CryptStringToBinary(cert_thumbprint_str,
- CERT_THUMBPRINT_STR_LEN,
- CRYPT_STRING_HEX,
- cert_thumbprint_data,
- &cert_thumbprint.cbData,
- NULL, NULL)) {
- curlx_unicodefree(cert_path);
- CertCloseStore(cert_store, 0);
- return CURLE_SSL_CERTPROBLEM;
- }
-
- client_certs[0] = CertFindCertificateInStore(
- cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_HASH, &cert_thumbprint, NULL);
-
- curlx_unicodefree(cert_path);
-
- if(client_certs[0]) {
- schannel_cred.cCreds = 1;
- schannel_cred.paCred = client_certs;
- }
- else {
- /* CRYPT_E_NOT_FOUND / E_INVALIDARG */
- CertCloseStore(cert_store, 0);
- return CURLE_SSL_CERTPROBLEM;
- }
- }
- CertCloseStore(cert_store, 0);
- }
-#else
- if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) {
- failf(data, "schannel: client cert support not built in");
- return CURLE_NOT_BUILT_IN;
- }
-#endif
-
- /* allocate memory for the re-usable credential handle */
- BACKEND->cred = (struct Curl_schannel_cred *)
- calloc(1, sizeof(struct Curl_schannel_cred));
- if(!BACKEND->cred) {
- failf(data, "schannel: unable to allocate memory");
-
- if(client_certs[0])
- CertFreeCertificateContext(client_certs[0]);
-
- return CURLE_OUT_OF_MEMORY;
- }
- BACKEND->cred->refcount = 1;
-
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
- */
- sspi_status =
- s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
- SECPKG_CRED_OUTBOUND, NULL,
- &schannel_cred, NULL, NULL,
- &BACKEND->cred->cred_handle,
- &BACKEND->cred->time_stamp);
-
- if(client_certs[0])
- CertFreeCertificateContext(client_certs[0]);
-
- if(sspi_status != SEC_E_OK) {
- char buffer[STRERROR_LEN];
- failf(data, "schannel: AcquireCredentialsHandle failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- Curl_safefree(BACKEND->cred);
- switch(sspi_status) {
- case SEC_E_INSUFFICIENT_MEMORY:
- return CURLE_OUT_OF_MEMORY;
- case SEC_E_NO_CREDENTIALS:
- case SEC_E_SECPKG_NOT_FOUND:
- case SEC_E_NOT_OWNER:
- case SEC_E_UNKNOWN_CREDENTIALS:
- case SEC_E_INTERNAL_ERROR:
- default:
- return CURLE_SSL_CONNECT_ERROR;
- }
+ result = schannel_acquire_credential_handle(data, conn, sockindex);
+ if(result != CURLE_OK) {
+ return result;
}
}
@@ -844,7 +860,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
|| Curl_inet_pton(AF_INET6, hostname, &addr6)
#endif
) {
- infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
+ infof(data, "schannel: using IP address, SNI is not supported by OS.");
}
#ifdef HAS_ALPN
@@ -877,14 +893,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
alpn_buffer[cur++] = ALPN_H2_LENGTH;
memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH);
cur += ALPN_H2_LENGTH;
- infof(data, "schannel: ALPN, offering %s\n", ALPN_H2);
+ infof(data, "schannel: ALPN, offering %s", ALPN_H2);
}
#endif
alpn_buffer[cur++] = ALPN_HTTP_1_1_LENGTH;
memcpy(&alpn_buffer[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
cur += ALPN_HTTP_1_1_LENGTH;
- infof(data, "schannel: ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "schannel: ALPN, offering %s", ALPN_HTTP_1_1);
*list_len = curlx_uitous(cur - list_start_index);
*extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short);
@@ -972,7 +988,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
DEBUGF(infof(data, "schannel: sending initial handshake data: "
- "sending %lu bytes...\n", outbuf.cbBuffer));
+ "sending %lu bytes.", outbuf.cbBuffer));
/* send initial handshake data which is now stored in output buffer */
result = Curl_write_plain(data, conn->sock[sockindex], outbuf.pvBuffer,
@@ -985,7 +1001,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
}
DEBUGF(infof(data, "schannel: sent initial handshake data: "
- "sent %zd bytes\n", written));
+ "sent %zd bytes", written));
BACKEND->recv_unrecoverable_err = CURLE_OK;
BACKEND->recv_sspi_close_notify = false;
@@ -1019,7 +1035,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
+ "schannel: SSL/TLS connection with %s port %hu (step 2/3)",
hostname, conn->remote_port));
if(!BACKEND->cred || !BACKEND->ctxt)
@@ -1081,7 +1097,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(connssl->connecting_state != ssl_connect_2_writing)
connssl->connecting_state = ssl_connect_2_reading;
DEBUGF(infof(data, "schannel: failed to receive handshake, "
- "need more data\n"));
+ "need more data"));
return CURLE_OK;
}
else if((result != CURLE_OK) || (nread == 0)) {
@@ -1093,11 +1109,11 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* increase encrypted data buffer offset */
BACKEND->encdata_offset += nread;
BACKEND->encdata_is_incomplete = false;
- DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
+ DEBUGF(infof(data, "schannel: encrypted data got %zd", nread));
}
DEBUGF(infof(data,
- "schannel: encrypted data buffer: offset %zu length %zu\n",
+ "schannel: encrypted data buffer: offset %zu length %zu",
BACKEND->encdata_offset, BACKEND->encdata_length));
/* setup input buffers */
@@ -1142,7 +1158,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
BACKEND->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading;
DEBUGF(infof(data,
- "schannel: received incomplete message, need more data\n"));
+ "schannel: received incomplete message, need more data"));
return CURLE_OK;
}
@@ -1154,7 +1170,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
connssl->connecting_state = ssl_connect_2_writing;
DEBUGF(infof(data,
- "schannel: a client certificate has been requested\n"));
+ "schannel: a client certificate has been requested"));
return CURLE_OK;
}
@@ -1164,7 +1180,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* search for handshake tokens that need to be send */
if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
DEBUGF(infof(data, "schannel: sending next handshake data: "
- "sending %lu bytes...\n", outbuf[i].cbBuffer));
+ "sending %lu bytes.", outbuf[i].cbBuffer));
/* send handshake token to server */
result = Curl_write_plain(data, conn->sock[sockindex],
@@ -1219,7 +1235,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* check if there was additional remaining encrypted data */
if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
- DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
+ DEBUGF(infof(data, "schannel: encrypted data length: %lu",
inbuf[1].cbBuffer));
/*
There are two cases where we could be getting extra data here:
@@ -1259,7 +1275,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
/* check if the handshake is complete */
if(sspi_status == SEC_E_OK) {
connssl->connecting_state = ssl_connect_3;
- DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n"));
+ DEBUGF(infof(data, "schannel: SSL/TLS handshake complete"));
}
pubkey_ptr = SSL_PINNED_PUB_KEY();
@@ -1348,7 +1364,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
bool isproxy = SSL_IS_PROXY();
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
const char * const hostname = SSL_HOST_NAME();
#endif
#ifdef HAS_ALPN
@@ -1358,7 +1374,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGF(infof(data,
- "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
+ "schannel: SSL/TLS connection with %s port %hu (step 3/3)",
hostname, conn->remote_port));
if(!BACKEND->cred)
@@ -1394,7 +1410,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(alpn_result.ProtoNegoStatus ==
SecApplicationProtocolNegotiationStatus_Success) {
- infof(data, "schannel: ALPN, server accepted to use %.*s\n",
+ infof(data, "schannel: ALPN, server accepted to use %.*s",
alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
#ifdef USE_HTTP2
@@ -1411,7 +1427,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
}
}
else
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
@@ -1428,7 +1444,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(incache) {
if(old_cred != BACKEND->cred) {
DEBUGF(infof(data,
- "schannel: old credential handle is stale, removing\n"));
+ "schannel: old credential handle is stale, removing"));
/* we're not taking old_cred ownership here, no refcount++ is needed */
Curl_ssl_delsessionid(data, (void *)old_cred);
incache = FALSE;
@@ -1447,7 +1463,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
/* this cred session is now also referenced by sessionid cache */
BACKEND->cred->refcount++;
DEBUGF(infof(data,
- "schannel: stored credential handle in session cache\n"));
+ "schannel: stored credential handle in session cache"));
}
}
Curl_ssl_sessionid_unlock(data);
@@ -1778,21 +1794,21 @@ schannel_recv(struct Curl_easy *data, int sockindex,
* handled in the cleanup.
*/
- DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len));
+ DEBUGF(infof(data, "schannel: client wants to read %zu bytes", len));
*err = CURLE_OK;
if(len && len <= BACKEND->decdata_offset) {
- infof(data, "schannel: enough decrypted data is already available\n");
+ infof(data, "schannel: enough decrypted data is already available");
goto cleanup;
}
else if(BACKEND->recv_unrecoverable_err) {
*err = BACKEND->recv_unrecoverable_err;
- infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
+ infof(data, "schannel: an unrecoverable error occurred in a prior call");
goto cleanup;
}
else if(BACKEND->recv_sspi_close_notify) {
/* once a server has indicated shutdown there is no more encrypted data */
- infof(data, "schannel: server indicated shutdown in a prior call\n");
+ infof(data, "schannel: server indicated shutdown in a prior call");
goto cleanup;
}
@@ -1821,12 +1837,12 @@ schannel_recv(struct Curl_easy *data, int sockindex,
BACKEND->encdata_buffer = reallocated_buffer;
BACKEND->encdata_length = reallocated_length;
size = BACKEND->encdata_length - BACKEND->encdata_offset;
- DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n",
+ DEBUGF(infof(data, "schannel: encdata_buffer resized %zu",
BACKEND->encdata_length));
}
DEBUGF(infof(data,
- "schannel: encrypted data buffer: offset %zu length %zu\n",
+ "schannel: encrypted data buffer: offset %zu length %zu",
BACKEND->encdata_offset, BACKEND->encdata_length));
/* read encrypted data from socket */
@@ -1838,25 +1854,25 @@ schannel_recv(struct Curl_easy *data, int sockindex,
nread = -1;
if(*err == CURLE_AGAIN)
DEBUGF(infof(data,
- "schannel: Curl_read_plain returned CURLE_AGAIN\n"));
+ "schannel: Curl_read_plain returned CURLE_AGAIN"));
else if(*err == CURLE_RECV_ERROR)
- infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n");
+ infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR");
else
- infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
+ infof(data, "schannel: Curl_read_plain returned error %d", *err);
}
else if(nread == 0) {
BACKEND->recv_connection_closed = true;
- DEBUGF(infof(data, "schannel: server closed the connection\n"));
+ DEBUGF(infof(data, "schannel: server closed the connection"));
}
else if(nread > 0) {
BACKEND->encdata_offset += (size_t)nread;
BACKEND->encdata_is_incomplete = false;
- DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread));
+ DEBUGF(infof(data, "schannel: encrypted data got %zd", nread));
}
}
DEBUGF(infof(data,
- "schannel: encrypted data buffer: offset %zu length %zu\n",
+ "schannel: encrypted data buffer: offset %zu length %zu",
BACKEND->encdata_offset, BACKEND->encdata_length));
/* decrypt loop */
@@ -1885,7 +1901,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* check for successfully decrypted data, even before actual
renegotiation or shutdown of the connection context */
if(inbuf[1].BufferType == SECBUFFER_DATA) {
- DEBUGF(infof(data, "schannel: decrypted data length: %lu\n",
+ DEBUGF(infof(data, "schannel: decrypted data length: %lu",
inbuf[1].cbBuffer));
/* increase buffer in order to fit the received amount of data */
@@ -1918,15 +1934,15 @@ schannel_recv(struct Curl_easy *data, int sockindex,
BACKEND->decdata_offset += size;
}
- DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size));
+ DEBUGF(infof(data, "schannel: decrypted data added: %zu", size));
DEBUGF(infof(data,
- "schannel: decrypted cached: offset %zu length %zu\n",
+ "schannel: decrypted cached: offset %zu length %zu",
BACKEND->decdata_offset, BACKEND->decdata_length));
}
/* check for remaining encrypted data */
if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
- DEBUGF(infof(data, "schannel: encrypted data length: %lu\n",
+ DEBUGF(infof(data, "schannel: encrypted data length: %lu",
inbuf[3].cbBuffer));
/* check if the remaining data is less than the total amount
@@ -1942,7 +1958,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
}
DEBUGF(infof(data,
- "schannel: encrypted cached: offset %zu length %zu\n",
+ "schannel: encrypted cached: offset %zu length %zu",
BACKEND->encdata_offset, BACKEND->encdata_length));
}
else {
@@ -1952,29 +1968,29 @@ schannel_recv(struct Curl_easy *data, int sockindex,
/* check if server wants to renegotiate the connection context */
if(sspi_status == SEC_I_RENEGOTIATE) {
- infof(data, "schannel: remote party requests renegotiation\n");
+ infof(data, "schannel: remote party requests renegotiation");
if(*err && *err != CURLE_AGAIN) {
- infof(data, "schannel: can't renogotiate, an error is pending\n");
+ infof(data, "schannel: can't renogotiate, an error is pending");
goto cleanup;
}
if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renogotiate, "
- "encrypted data available\n");
+ "encrypted data available");
goto cleanup;
}
/* begin renegotiation */
- infof(data, "schannel: renegotiating SSL/TLS connection\n");
+ infof(data, "schannel: renegotiating SSL/TLS connection");
connssl->state = ssl_connection_negotiating;
connssl->connecting_state = ssl_connect_2_writing;
*err = schannel_connect_common(data, conn, sockindex, FALSE, &done);
if(*err) {
- infof(data, "schannel: renegotiation failed\n");
+ infof(data, "schannel: renegotiation failed");
goto cleanup;
}
/* now retry receiving data */
sspi_status = SEC_E_OK;
- infof(data, "schannel: SSL/TLS connection renegotiated\n");
+ infof(data, "schannel: SSL/TLS connection renegotiated");
continue;
}
/* check if the server closed the connection */
@@ -1984,7 +2000,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
BACKEND->recv_sspi_close_notify = true;
if(!BACKEND->recv_connection_closed) {
BACKEND->recv_connection_closed = true;
- infof(data, "schannel: server closed the connection\n");
+ infof(data, "schannel: server closed the connection");
}
goto cleanup;
}
@@ -1993,7 +2009,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
BACKEND->encdata_is_incomplete = true;
if(!*err)
*err = CURLE_AGAIN;
- infof(data, "schannel: failed to decrypt data, need more data\n");
+ infof(data, "schannel: failed to decrypt data, need more data");
goto cleanup;
}
else {
@@ -2001,23 +2017,23 @@ schannel_recv(struct Curl_easy *data, int sockindex,
char buffer[STRERROR_LEN];
#endif
*err = CURLE_RECV_ERROR;
- infof(data, "schannel: failed to read data from server: %s\n",
+ infof(data, "schannel: failed to read data from server: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
goto cleanup;
}
}
DEBUGF(infof(data,
- "schannel: encrypted data buffer: offset %zu length %zu\n",
+ "schannel: encrypted data buffer: offset %zu length %zu",
BACKEND->encdata_offset, BACKEND->encdata_length));
DEBUGF(infof(data,
- "schannel: decrypted data buffer: offset %zu length %zu\n",
+ "schannel: decrypted data buffer: offset %zu length %zu",
BACKEND->decdata_offset, BACKEND->decdata_length));
cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
- DEBUGF(infof(data, "schannel: schannel_recv cleanup\n"));
+ DEBUGF(infof(data, "schannel: schannel_recv cleanup"));
/* Error if the connection has closed without a close_notify.
@@ -2039,7 +2055,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
BACKEND->recv_sspi_close_notify = true;
else {
*err = CURLE_RECV_ERROR;
- infof(data, "schannel: server closed abruptly (missing close_notify)\n");
+ infof(data, "schannel: server closed abruptly (missing close_notify)");
}
}
@@ -2053,9 +2069,9 @@ schannel_recv(struct Curl_easy *data, int sockindex,
memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
BACKEND->decdata_offset - size);
BACKEND->decdata_offset -= size;
- DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size));
+ DEBUGF(infof(data, "schannel: decrypted data returned %zu", size));
DEBUGF(infof(data,
- "schannel: decrypted data buffer: offset %zu length %zu\n",
+ "schannel: decrypted data buffer: offset %zu length %zu",
BACKEND->decdata_offset, BACKEND->decdata_length));
*err = CURLE_OK;
return (ssize_t)size;
@@ -2139,7 +2155,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
DEBUGASSERT(data);
- infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
+ infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu",
hostname, conn->remote_port);
if(BACKEND->cred && BACKEND->ctxt) {
@@ -2197,14 +2213,14 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
s_pSecFn->FreeContextBuffer(outbuf.pvBuffer);
if((result != CURLE_OK) || (outbuf.cbBuffer != (size_t) written)) {
infof(data, "schannel: failed to send close msg: %s"
- " (bytes written: %zd)\n", curl_easy_strerror(result), written);
+ " (bytes written: %zd)", curl_easy_strerror(result), written);
}
}
}
/* free SSPI Schannel API security context handle */
if(BACKEND->ctxt) {
- DEBUGF(infof(data, "schannel: clear security context handle\n"));
+ DEBUGF(infof(data, "schannel: clear security context handle"));
s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
Curl_safefree(BACKEND->ctxt);
}
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index 25d47b808..1b283d045 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -80,7 +80,7 @@ static int is_cr_or_lf(char c)
/* Search the substring needle,needlelen into string haystack,haystacklen
* Strings don't need to be terminated by a '\0'.
* Similar of OSX/Linux memmem (not available on Visual Studio).
- * Return position of beginning of first occurence or NULL if not found
+ * Return position of beginning of first occurrence or NULL if not found
*/
static const char *c_memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
@@ -204,12 +204,12 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
if(result == CURLE_OK) {
if(!num_certs) {
infof(data,
- "schannel: did not add any certificates from CA file '%s'\n",
+ "schannel: did not add any certificates from CA file '%s'",
ca_file_text);
}
else {
infof(data,
- "schannel: added %d certificate(s) from CA file '%s'\n",
+ "schannel: added %d certificate(s) from CA file '%s'",
num_certs, ca_file_text);
}
}
@@ -526,7 +526,7 @@ static CURLcode verify_host(struct Curl_easy *data,
if(match_result == CURL_HOST_MATCH) {
infof(data,
"schannel: connection hostname (%s) validated "
- "against certificate name (%s)\n",
+ "against certificate name (%s)",
conn_hostname, cert_hostname);
result = CURLE_OK;
}
@@ -535,7 +535,7 @@ static CURLcode verify_host(struct Curl_easy *data,
infof(data,
"schannel: connection hostname (%s) did not match "
- "against certificate name (%s)\n",
+ "against certificate name (%s)",
conn_hostname, cert_hostname);
cert_hostname_len =
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index edd375ea7..1e6ed5f06 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -32,6 +32,9 @@
#include "curl_base64.h"
#include "strtok.h"
#include "multiif.h"
+#include "strcase.h"
+#include "x509asn1.h"
+#include "strerror.h"
#ifdef USE_SECTRANSP
@@ -1644,7 +1647,7 @@ static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
}
}
/* All cipher suites in the list are found. Report to logs as-is */
- infof(data, "SSL: Setting cipher suites list \"%s\"\n", ciphers);
+ infof(data, "SSL: Setting cipher suites list \"%s\"", ciphers);
err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count);
if(err != noErr) {
@@ -1840,19 +1843,19 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
#endif
) {
CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
- infof(data, "ALPN, offering %s\n", ALPN_H2);
+ infof(data, "ALPN, offering %s", ALPN_H2);
}
#endif
CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
/* expects length prefixed preference ordered list of protocols in wire
* format
*/
err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
if(err != noErr)
- infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
+ infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
err);
CFRelease(alpnArr);
}
@@ -1861,7 +1864,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
if(SSL_SET_OPTION(key)) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
- "Transport. The private key must be in the Keychain.\n");
+ "Transport. The private key must be in the Keychain.");
}
if(ssl_cert || ssl_cert_blob) {
@@ -1869,24 +1872,28 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
SecIdentityRef cert_and_key = NULL;
- /* User wants to authenticate with a client cert. Look for it:
- If we detect that this is a file on disk, then let's load it.
- Otherwise, assume that the user wants to use an identity loaded
- from the Keychain. */
- if(is_cert_file || is_cert_data) {
+ /* User wants to authenticate with a client cert. Look for it. Assume that
+ the user wants to use an identity loaded from the Keychain. If not, try
+ it as a file on disk */
+
+ if(!is_cert_data)
+ err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
+ else
+ err = !noErr;
+ if((err != noErr) && (is_cert_file || is_cert_data)) {
if(!SSL_SET_OPTION(cert_type))
- infof(data, "WARNING: SSL: Certificate type not set, assuming "
- "PKCS#12 format.\n");
- else if(strncmp(SSL_SET_OPTION(cert_type), "P12",
- strlen(SSL_SET_OPTION(cert_type))) != 0)
- infof(data, "WARNING: SSL: The Security framework only supports "
- "loading identities that are in PKCS#12 format.\n");
+ infof(data, "SSL: Certificate type not set, assuming "
+ "PKCS#12 format.");
+ else if(!strcasecompare(SSL_SET_OPTION(cert_type), "P12")) {
+ failf(data, "SSL: The Security framework only supports "
+ "loading identities that are in PKCS#12 format.");
+ return CURLE_SSL_CERTPROBLEM;
+ }
err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
- SSL_SET_OPTION(key_passwd), &cert_and_key);
+ SSL_SET_OPTION(key_passwd),
+ &cert_and_key);
}
- else
- err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
if(err == noErr && cert_and_key) {
SecCertificateRef cert = NULL;
@@ -1899,7 +1906,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
char *certp;
CURLcode result = CopyCertSubject(data, cert, &certp);
if(!result) {
- infof(data, "Client certificate: %s\n", certp);
+ infof(data, "Client certificate: %s", certp);
free(certp);
}
@@ -2025,7 +2032,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
strlen(hostname));
if(err != noErr) {
- infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
+ infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
err);
}
@@ -2035,11 +2042,11 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
#endif
) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
- "the OS.\n");
+ "the OS.");
}
}
else {
- infof(data, "WARNING: disabling hostname validation also disables SNI.\n");
+ infof(data, "WARNING: disabling hostname validation also disables SNI.");
}
ciphers = SSL_CONN_CONFIG(cipher_list);
@@ -2082,7 +2089,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
- infof(data, "SSL re-using session ID\n");
+ infof(data, "SSL re-using session ID");
}
/* If there isn't one, then let's make one up! This has to be done prior
to starting the handshake. */
@@ -2487,7 +2494,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
spkiHeaderLength = 23;
break;
default:
- infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
+ infof(data, "SSL: unhandled public key length: %d", pubkeylen);
#elif SECTRANSP_PINNEDPUBKEY_V2
default:
/* ecDSA secp256r1 pubkeylen == 91 header already included?
@@ -2778,35 +2785,35 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
(void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
switch(protocol) {
case kSSLProtocol2:
- infof(data, "SSL 2.0 connection using %s\n",
+ infof(data, "SSL 2.0 connection using %s",
TLSCipherNameForNumber(cipher));
break;
case kSSLProtocol3:
- infof(data, "SSL 3.0 connection using %s\n",
+ infof(data, "SSL 3.0 connection using %s",
TLSCipherNameForNumber(cipher));
break;
case kTLSProtocol1:
- infof(data, "TLS 1.0 connection using %s\n",
+ infof(data, "TLS 1.0 connection using %s",
TLSCipherNameForNumber(cipher));
break;
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
case kTLSProtocol11:
- infof(data, "TLS 1.1 connection using %s\n",
+ infof(data, "TLS 1.1 connection using %s",
TLSCipherNameForNumber(cipher));
break;
case kTLSProtocol12:
- infof(data, "TLS 1.2 connection using %s\n",
+ infof(data, "TLS 1.2 connection using %s",
TLSCipherNameForNumber(cipher));
break;
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
case kTLSProtocol13:
- infof(data, "TLS 1.3 connection using %s\n",
+ infof(data, "TLS 1.3 connection using %s",
TLSCipherNameForNumber(cipher));
break;
#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
default:
- infof(data, "Unknown protocol connection\n");
+ infof(data, "Unknown protocol connection");
break;
}
@@ -2832,7 +2839,7 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
conn->negnpn = CURL_HTTP_VERSION_1_1;
}
else
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
@@ -2849,13 +2856,60 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
}
+static CURLcode
+add_cert_to_certinfo(struct Curl_easy *data,
+ SecCertificateRef server_cert,
+ int idx)
+{
+ CURLcode result = CURLE_OK;
+ const char *beg;
+ const char *end;
+ CFDataRef cert_data = SecCertificateCopyData(server_cert);
+
+ if(!cert_data)
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ beg = (const char *)CFDataGetBytePtr(cert_data);
+ end = beg + CFDataGetLength(cert_data);
+ result = Curl_extract_certinfo(data, idx, beg, end);
+ CFRelease(cert_data);
+ return result;
+}
+
+static CURLcode
+collect_server_cert_single(struct Curl_easy *data,
+ SecCertificateRef server_cert,
+ CFIndex idx)
+{
+ CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(data->set.verbose) {
+ char *certp;
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s", certp);
+ free(certp);
+ }
+ }
+#endif
+ if(data->set.ssl.certinfo)
+ result = add_cert_to_certinfo(data, server_cert, (int)idx);
+ return result;
+}
+
/* This should be called during step3 of the connection at the earliest */
-static void
-show_verbose_server_cert(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode
+collect_server_cert(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ const bool show_verbose_server_cert = data->set.verbose;
+#else
+ const bool show_verbose_server_cert = false;
+#endif
+ CURLcode result = data->set.ssl.certinfo ?
+ CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CFArrayRef server_certs = NULL;
@@ -2864,8 +2918,11 @@ show_verbose_server_cert(struct Curl_easy *data,
CFIndex i, count;
SecTrustRef trust = NULL;
+ if(!show_verbose_server_cert && !data->set.ssl.certinfo)
+ return CURLE_OK;
+
if(!backend->ssl_ctx)
- return;
+ return result;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS
@@ -2875,15 +2932,11 @@ show_verbose_server_cert(struct Curl_easy *data,
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- CURLcode result;
- char *certp;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(trust);
}
@@ -2901,15 +2954,11 @@ show_verbose_server_cert(struct Curl_easy *data,
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- char *certp;
- CURLcode result;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(trust);
}
@@ -2920,16 +2969,12 @@ show_verbose_server_cert(struct Curl_easy *data,
/* Just in case SSLCopyPeerCertificates() returns null too... */
if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- char *certp;
- CURLcode result;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(server_certs);
}
@@ -2941,21 +2986,17 @@ show_verbose_server_cert(struct Curl_easy *data,
err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
if(err == noErr) {
count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- CURLcode result;
- char *certp;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s\n", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(server_certs);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ return result;
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
static CURLcode
sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
@@ -2964,12 +3005,11 @@ sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* There is no step 3!
- * Well, okay, if verbose mode is on, let's print the details of the
- * server certificates. */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- if(data->set.verbose)
- show_verbose_server_cert(data, conn, sockindex);
-#endif
+ * Well, okay, let's collect server certificates, and if verbose mode is on,
+ * let's print the details of the server certificates. */
+ const CURLcode result = collect_server_cert(data, conn, sockindex);
+ if(result)
+ return result;
connssl->connecting_state = ssl_connect_done;
return CURLE_OK;
@@ -3148,6 +3188,7 @@ static int sectransp_shutdown(struct Curl_easy *data,
int what;
int rc;
char buf[120];
+ int loop = 10; /* avoid getting stuck */
if(!backend->ssl_ctx)
return 0;
@@ -3163,7 +3204,7 @@ static int sectransp_shutdown(struct Curl_easy *data,
what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
- for(;;) {
+ while(loop--) {
if(what < 0) {
/* anything that gets here is fatally bad */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -3182,7 +3223,9 @@ static int sectransp_shutdown(struct Curl_easy *data,
nread = read(conn->sock[sockindex], buf, sizeof(buf));
if(nread < 0) {
- failf(data, "read: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "read: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
rc = -1;
}
@@ -3427,6 +3470,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
{ CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
SSLSUPP_CAINFO_BLOB |
+ SSLSUPP_CERTINFO |
#ifdef SECTRANSP_PINNEDPUBKEY
SSLSUPP_PINNEDPUBKEY,
#else
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index 65f4f773d..e5bbe1f5f 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -125,6 +125,16 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
return !memcmp(first->data, second->data, first->len); /* same data */
}
+static bool safecmp(char *a, char *b)
+{
+ if(a && b)
+ return !strcmp(a, b);
+ else if(!a && !b)
+ return TRUE; /* match */
+ return FALSE; /* no match */
+}
+
+
bool
Curl_ssl_config_matches(struct ssl_primary_config *data,
struct ssl_primary_config *needle)
@@ -136,11 +146,13 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
(data->verifystatus == needle->verifystatus) &&
blobcmp(data->cert_blob, needle->cert_blob) &&
blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
- Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
- Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
- Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
- Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
- Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
+ blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
+ safecmp(data->CApath, needle->CApath) &&
+ safecmp(data->CAfile, needle->CAfile) &&
+ safecmp(data->issuercert, needle->issuercert) &&
+ safecmp(data->clientcert, needle->clientcert) &&
+ safecmp(data->random_file, needle->random_file) &&
+ safecmp(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
Curl_safe_strcasecompare(data->curves, needle->curves) &&
@@ -163,8 +175,10 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_BLOB(cert_blob);
CLONE_BLOB(ca_info_blob);
+ CLONE_BLOB(issuercert_blob);
CLONE_STRING(CApath);
CLONE_STRING(CAfile);
+ CLONE_STRING(issuercert);
CLONE_STRING(clientcert);
CLONE_STRING(random_file);
CLONE_STRING(egdsocket);
@@ -180,6 +194,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->issuercert);
Curl_safefree(sslc->clientcert);
Curl_safefree(sslc->random_file);
Curl_safefree(sslc->egdsocket);
@@ -188,6 +203,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
Curl_safefree(sslc->pinned_key);
Curl_safefree(sslc->cert_blob);
Curl_safefree(sslc->ca_info_blob);
+ Curl_safefree(sslc->issuercert_blob);
Curl_safefree(sslc->curves);
}
@@ -326,7 +342,7 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
CURLcode
Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, bool *done)
+ bool isproxy, int sockindex, bool *done)
{
CURLcode result;
@@ -345,7 +361,7 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
if(result)
conn->ssl[sockindex].use = FALSE;
- else if(*done)
+ else if(*done && !isproxy)
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
return result;
}
@@ -407,8 +423,9 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
- if(!SSL_SET_OPTION(primary.sessionid))
- /* session ID re-use is disabled */
+ if(!SSL_SET_OPTION(primary.sessionid) || !data->state.session)
+ /* session ID re-use is disabled or the session cache has not been
+ setup */
return TRUE;
/* Lock if shared */
@@ -443,6 +460,10 @@ bool Curl_ssl_getsessionid(struct Curl_easy *data,
}
}
+ DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
+ no_match? "Didn't find": "Found",
+ isProxy ? "proxy" : "host",
+ conn->handler->scheme, name, port));
return no_match;
}
@@ -492,14 +513,14 @@ void Curl_ssl_delsessionid(struct Curl_easy *data, void *ssl_sessionid)
*/
CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
struct connectdata *conn,
- bool isProxy,
+ const bool isProxy,
void *ssl_sessionid,
size_t idsize,
int sockindex)
{
size_t i;
- struct Curl_ssl_session *store = &data->state.session[0];
- long oldest_age = data->state.session[0].age; /* zero if unused */
+ struct Curl_ssl_session *store;
+ long oldest_age;
char *clone_host;
char *clone_conn_to_host;
int conn_to_port;
@@ -515,6 +536,11 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
const char *hostname = conn->host.name;
#endif
(void)sockindex;
+ if(!data->state.session)
+ return CURLE_OK;
+
+ store = &data->state.session[0];
+ oldest_age = data->state.session[0].age; /* zero if unused */
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
clone_host = strdup(hostname);
@@ -583,6 +609,9 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
+ DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
+ store->scheme, store->name, store->remote_port,
+ isProxy ? "PROXY" : "server"));
return CURLE_OK;
}
@@ -708,12 +737,12 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
static size_t multissl_version(char *buffer, size_t size);
-size_t Curl_ssl_version(char *buffer, size_t size)
+void Curl_ssl_version(char *buffer, size_t size)
{
#ifdef CURL_WITH_MULTI_SSL
- return multissl_version(buffer, size);
+ (void)multissl_version(buffer, size);
#else
- return Curl_ssl->version(buffer, size);
+ (void)Curl_ssl->version(buffer, size);
#endif
}
@@ -940,7 +969,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
if(encode)
return encode;
- infof(data, "\t public key hash: sha256//%s\n", encoded);
+ infof(data, " public key hash: sha256//%s", encoded);
/* it starts with sha256//, copy so we can modify it */
pinkeylen = strlen(pinnedpubkey) + 1;
@@ -1374,7 +1403,7 @@ static int multissl_setup(const struct Curl_ssl *backend)
for(i = 0; available_backends[i]; i++) {
if(strcasecompare(env, available_backends[i]->info.name)) {
Curl_ssl = available_backends[i];
- curl_free(env_tmp);
+ free(env_tmp);
return 0;
}
}
@@ -1382,7 +1411,7 @@ static int multissl_setup(const struct Curl_ssl *backend)
/* Fall back to first available backend */
Curl_ssl = available_backends[0];
- curl_free(env_tmp);
+ free(env_tmp);
return 0;
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 7f93e7aed..beaa83d9e 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -193,6 +193,7 @@ CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
int sockindex);
CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
struct connectdata *conn,
+ bool isproxy,
int sockindex,
bool *done);
/* tell the SSL stuff to close down all open information regarding
@@ -209,7 +210,7 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);
/* init the SSL session ID cache */
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
-size_t Curl_ssl_version(char *buffer, size_t size);
+void Curl_ssl_version(char *buffer, size_t size);
bool Curl_ssl_data_pending(const struct connectdata *conn,
int connindex);
int Curl_ssl_check_cxn(struct connectdata *conn);
@@ -246,7 +247,7 @@ void Curl_ssl_sessionid_unlock(struct Curl_easy *data);
*/
bool Curl_ssl_getsessionid(struct Curl_easy *data,
struct connectdata *conn,
- const bool isproxy,
+ const bool isProxy,
void **ssl_sessionid,
size_t *idsize, /* set 0 if unknown */
int sockindex);
@@ -313,7 +314,7 @@ void Curl_ssl_detach_conn(struct Curl_easy *data,
#define Curl_ssl_data_pending(x,y) 0
#define Curl_ssl_check_cxn(x) 0
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
-#define Curl_ssl_connect_nonblocking(x,y,z,w) CURLE_NOT_BUILT_IN
+#define Curl_ssl_connect_nonblocking(x,y,z,w,a) CURLE_NOT_BUILT_IN
#define Curl_ssl_kill_session(x) Curl_nop_stmt
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
#define Curl_ssl_cert_status_request() FALSE
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 60e27e366..16fbb8928 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -239,7 +239,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
req_method = SSLv23_client_method();
#else
infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
- "TLS 1.0 is used exclusively\n");
+ "TLS 1.0 is used exclusively");
req_method = TLSv1_client_method();
#endif
use_sni(TRUE);
@@ -324,7 +324,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
failf(data, "failed setting cipher list: %s", ciphers);
return CURLE_SSL_CIPHER;
}
- infof(data, "Cipher selection: %s\n", ciphers);
+ infof(data, "Cipher selection: %s", ciphers);
}
#ifndef NO_FILESYSTEM
@@ -347,16 +347,16 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
/* Just continue with a warning if no strict certificate
verification is required. */
infof(data, "error setting certificate verify locations,"
- " continuing anyway:\n");
+ " continuing anyway:");
}
}
else {
/* Everything is fine. */
- infof(data, "successfully set certificate verify locations:\n");
+ infof(data, "successfully set certificate verify locations:");
}
- infof(data, " CAfile: %s\n",
+ infof(data, " CAfile: %s",
SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
- infof(data, " CApath: %s\n",
+ infof(data, " CApath: %s",
SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
}
@@ -406,7 +406,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname,
(unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) "
- "TLS extension\n");
+ "TLS extension");
}
}
#endif
@@ -450,12 +450,12 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(data->state.httpwant >= CURL_HTTP_VERSION_2) {
strcpy(protocols + strlen(protocols), ALPN_H2 ",");
- infof(data, "ALPN, offering %s\n", ALPN_H2);
+ infof(data, "ALPN, offering %s", ALPN_H2);
}
#endif
strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
if(wolfSSL_UseALPN(backend->handle, protocols,
(unsigned)strlen(protocols),
@@ -494,15 +494,11 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
&ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
- char error_buffer[WOLFSSL_MAX_ERROR_SZ];
- Curl_ssl_sessionid_unlock(data);
- failf(data, "SSL: SSL_set_session failed: %s",
- ERR_error_string(SSL_get_error(backend->handle, 0),
- error_buffer));
- return CURLE_SSL_CONNECT_ERROR;
+ Curl_ssl_delsessionid(data, ssl_sessionid);
+ infof(data, "Can't use session ID, going on without\n");
}
- /* Informational message */
- infof(data, "SSL re-using session ID\n");
+ else
+ infof(data, "SSL re-using session ID");
}
Curl_ssl_sessionid_unlock(data);
}
@@ -529,6 +525,8 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
const char * const dispname = SSL_HOST_DISPNAME();
const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
+ ERR_clear_error();
+
conn->recv[sockindex] = wolfssl_recv;
conn->send[sockindex] = wolfssl_send;
@@ -582,7 +580,7 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
* as also mismatching CN fields */
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
- failf(data, "\tsubject alt name(s) or common name do not match \"%s\"",
+ failf(data, " subject alt name(s) or common name do not match \"%s\"",
dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
@@ -594,13 +592,13 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
* 'conn->ssl_config.verifyhost' value. */
if(SSL_CONN_CONFIG(verifyhost)) {
failf(data,
- "\tsubject alt name(s) or common name do not match \"%s\"\n",
+ " subject alt name(s) or common name do not match \"%s\"\n",
dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
else {
infof(data,
- "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
+ " subject alt name(s) and/or common name do not match \"%s\"",
dispname);
return CURLE_OK;
}
@@ -609,14 +607,14 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
if(SSL_CONN_CONFIG(verifypeer)) {
- failf(data, "\tCA signer not available for verification");
+ failf(data, " CA signer not available for verification");
return CURLE_SSL_CACERT_BADFILE;
}
else {
/* Just continue with a warning if no strict certificate
verification is required. */
infof(data, "CA signer not available for verification, "
- "continuing anyway\n");
+ "continuing anyway");
}
}
#endif
@@ -681,7 +679,7 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
if(rc == SSL_SUCCESS) {
- infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
+ infof(data, "ALPN, server accepted to use %.*s", protocol_len,
protocol);
if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
@@ -694,13 +692,13 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
conn->negnpn = CURL_HTTP_VERSION_2;
#endif
else
- infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
+ infof(data, "ALPN, unrecognized protocol %.*s", protocol_len,
protocol);
Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
else if(rc == SSL_ALPN_NOT_FOUND)
- infof(data, "ALPN, server did not agree to a protocol\n");
+ infof(data, "ALPN, server did not agree to a protocol");
else {
failf(data, "ALPN, failure getting protocol, error %d", rc);
return CURLE_SSL_CONNECT_ERROR;
@@ -710,11 +708,11 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
connssl->connecting_state = ssl_connect_3;
#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
- infof(data, "SSL connection using %s / %s\n",
+ infof(data, "SSL connection using %s / %s",
wolfSSL_get_version(backend->handle),
wolfSSL_get_cipher_name(backend->handle));
#else
- infof(data, "SSL connected\n");
+ infof(data, "SSL connected");
#endif
return CURLE_OK;
@@ -743,7 +741,7 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
&old_ssl_sessionid, NULL, sockindex));
if(incache) {
if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
+ infof(data, "old SSL session ID is stale, removing");
Curl_ssl_delsessionid(data, old_ssl_sessionid);
incache = FALSE;
}
@@ -779,7 +777,11 @@ static ssize_t wolfssl_send(struct Curl_easy *data,
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
- int rc = SSL_write(backend->handle, mem, memlen);
+ int rc;
+
+ ERR_clear_error();
+
+ rc = SSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
int err = SSL_get_error(backend->handle, rc);
@@ -810,6 +812,10 @@ static void wolfssl_close(struct Curl_easy *data, struct connectdata *conn,
(void) data;
if(backend->handle) {
+ char buf[32];
+ /* Maybe the server has already sent a close notify alert.
+ Read it to avoid an RST on the TCP connection. */
+ (void)SSL_read(backend->handle, buf, (int)sizeof(buf));
(void)SSL_shutdown(backend->handle);
SSL_free(backend->handle);
backend->handle = NULL;
@@ -831,7 +837,11 @@ static ssize_t wolfssl_recv(struct Curl_easy *data,
struct ssl_backend_data *backend = connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
- int nread = SSL_read(backend->handle, buf, buffsize);
+ int nread;
+
+ ERR_clear_error();
+
+ nread = SSL_read(backend->handle, buf, buffsize);
if(nread < 0) {
int err = SSL_get_error(backend->handle, nread);
@@ -916,6 +926,7 @@ static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
(void) data;
if(backend->handle) {
+ ERR_clear_error();
SSL_free(backend->handle);
backend->handle = NULL;
}
@@ -1089,7 +1100,7 @@ static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
}
static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
+ CURLINFO info UNUSED_PARAM)
{
struct ssl_backend_data *backend = connssl->backend;
(void)info;
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index c0764c42d..15c8156d1 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -37,85 +37,23 @@
#include "warnless.h"
-#define CURL_MASK_SCHAR 0x7F
-#define CURL_MASK_UCHAR 0xFF
-
-#if (SIZEOF_SHORT == 2)
-# define CURL_MASK_SSHORT 0x7FFF
-# define CURL_MASK_USHORT 0xFFFF
-#elif (SIZEOF_SHORT == 4)
-# define CURL_MASK_SSHORT 0x7FFFFFFF
-# define CURL_MASK_USHORT 0xFFFFFFFF
-#elif (SIZEOF_SHORT == 8)
-# define CURL_MASK_SSHORT 0x7FFFFFFFFFFFFFFF
-# define CURL_MASK_USHORT 0xFFFFFFFFFFFFFFFF
-#else
-# error "SIZEOF_SHORT not defined"
-#endif
-
-#if (SIZEOF_INT == 2)
-# define CURL_MASK_SINT 0x7FFF
-# define CURL_MASK_UINT 0xFFFF
-#elif (SIZEOF_INT == 4)
-# define CURL_MASK_SINT 0x7FFFFFFF
-# define CURL_MASK_UINT 0xFFFFFFFF
-#elif (SIZEOF_INT == 8)
-# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFF
-# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFF
-#elif (SIZEOF_INT == 16)
-# define CURL_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-# define CURL_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-#else
-# error "SIZEOF_INT not defined"
-#endif
-
-#if (SIZEOF_LONG == 2)
-# define CURL_MASK_SLONG 0x7FFFL
-# define CURL_MASK_ULONG 0xFFFFUL
-#elif (SIZEOF_LONG == 4)
-# define CURL_MASK_SLONG 0x7FFFFFFFL
-# define CURL_MASK_ULONG 0xFFFFFFFFUL
-#elif (SIZEOF_LONG == 8)
-# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFL
-# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFUL
-#elif (SIZEOF_LONG == 16)
-# define CURL_MASK_SLONG 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
-# define CURL_MASK_ULONG 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
-#else
-# error "SIZEOF_LONG not defined"
-#endif
-
-#if (SIZEOF_CURL_OFF_T == 2)
-# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFF)
-# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFF)
-#elif (SIZEOF_CURL_OFF_T == 4)
-# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFF)
-# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFF)
-#elif (SIZEOF_CURL_OFF_T == 8)
-# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
-# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF)
-#elif (SIZEOF_CURL_OFF_T == 16)
-# define CURL_MASK_SCOFFT CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
-# define CURL_MASK_UCOFFT CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
-#else
-# error "SIZEOF_CURL_OFF_T not defined"
-#endif
-
-#if (SIZEOF_SIZE_T == SIZEOF_SHORT)
-# define CURL_MASK_SSIZE_T CURL_MASK_SSHORT
-# define CURL_MASK_USIZE_T CURL_MASK_USHORT
-#elif (SIZEOF_SIZE_T == SIZEOF_INT)
-# define CURL_MASK_SSIZE_T CURL_MASK_SINT
-# define CURL_MASK_USIZE_T CURL_MASK_UINT
-#elif (SIZEOF_SIZE_T == SIZEOF_LONG)
-# define CURL_MASK_SSIZE_T CURL_MASK_SLONG
-# define CURL_MASK_USIZE_T CURL_MASK_ULONG
-#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T)
-# define CURL_MASK_SSIZE_T CURL_MASK_SCOFFT
-# define CURL_MASK_USIZE_T CURL_MASK_UCOFFT
-#else
-# error "SIZEOF_SIZE_T not defined"
-#endif
+#define CURL_MASK_UCHAR ((unsigned char)~0)
+#define CURL_MASK_SCHAR (CURL_MASK_UCHAR >> 1)
+
+#define CURL_MASK_USHORT ((unsigned short)~0)
+#define CURL_MASK_SSHORT (CURL_MASK_USHORT >> 1)
+
+#define CURL_MASK_UINT ((unsigned int)~0)
+#define CURL_MASK_SINT (CURL_MASK_UINT >> 1)
+
+#define CURL_MASK_ULONG ((unsigned long)~0)
+#define CURL_MASK_SLONG (CURL_MASK_ULONG >> 1)
+
+#define CURL_MASK_UCOFFT ((unsigned CURL_TYPEOF_CURL_OFF_T)~0)
+#define CURL_MASK_SCOFFT (CURL_MASK_UCOFFT >> 1)
+
+#define CURL_MASK_USIZE_T ((size_t)~0)
+#define CURL_MASK_SSIZE_T (CURL_MASK_USIZE_T >> 1)
/*
** unsigned long to unsigned short
@@ -207,7 +145,7 @@ unsigned long curlx_uztoul(size_t uznum)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
-#if (SIZEOF_LONG < SIZEOF_SIZE_T)
+#if ULONG_MAX < SIZE_T_MAX
DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG);
#endif
return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
@@ -228,7 +166,7 @@ unsigned int curlx_uztoui(size_t uznum)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
-#if (SIZEOF_INT < SIZEOF_SIZE_T)
+#if UINT_MAX < SIZE_T_MAX
DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT);
#endif
return (unsigned int)(uznum & (size_t) CURL_MASK_UINT);
@@ -250,7 +188,7 @@ int curlx_sltosi(long slnum)
#endif
DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < SIZEOF_LONG)
+#if INT_MAX < LONG_MAX
DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT);
#endif
return (int)(slnum & (long) CURL_MASK_SINT);
@@ -272,7 +210,7 @@ unsigned int curlx_sltoui(long slnum)
#endif
DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < SIZEOF_LONG)
+#if UINT_MAX < LONG_MAX
DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT);
#endif
return (unsigned int)(slnum & (long) CURL_MASK_UINT);
@@ -352,7 +290,7 @@ int curlx_sztosi(ssize_t sznum)
#endif
DEBUGASSERT(sznum >= 0);
-#if (SIZEOF_INT < SIZEOF_SIZE_T)
+#if INT_MAX < SSIZE_T_MAX
DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT);
#endif
return (int)(sznum & (ssize_t) CURL_MASK_SINT);
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index 281c97248..1bdaeadc8 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -23,7 +23,7 @@
#include "curl_setup.h"
#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL)
+ defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
#include <curl/curl.h>
#include "urldata.h"
@@ -34,6 +34,7 @@
#include "inet_pton.h"
#include "curl_base64.h"
#include "x509asn1.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -205,16 +206,16 @@ static const char *bool2str(const char *beg, const char *end)
*/
static const char *octet2str(const char *beg, const char *end)
{
- size_t n = end - beg;
- char *buf = NULL;
+ struct dynbuf buf;
+ CURLcode result;
- if(n <= (SIZE_T_MAX - 1) / 3) {
- buf = malloc(3 * n + 1);
- if(buf)
- for(n = 0; beg < end; n += 3)
- msnprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
- }
- return buf;
+ Curl_dyn_init(&buf, 3 * CURL_ASN1_MAX + 1);
+ result = Curl_dyn_addn(&buf, "", 0);
+
+ while(!result && beg < end)
+ result = Curl_dyn_addf(&buf, "%02x:", (unsigned char) *beg++);
+
+ return Curl_dyn_ptr(&buf);
}
static const char *bit2str(const char *beg, const char *end)
@@ -517,8 +518,8 @@ static const char *GTime2str(const char *beg, const char *end)
return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
beg, beg + 4, beg + 6,
beg + 8, beg + 10, sec1, sec2,
- fracl? ".": "", fracl, fracp,
- sep, tzl, tzp);
+ fracl? ".": "", (int)fracl, fracp,
+ sep, (int)tzl, tzp);
}
/*
@@ -558,7 +559,7 @@ static const char *UTime2str(const char *beg, const char *end)
return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
20 - (*beg >= '5'), beg, beg + 2, beg + 4,
beg + 6, beg + 8, sec,
- tzl, tzp);
+ (int)tzl, tzp);
}
/*
@@ -866,7 +867,7 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, label, output);
if(!certnum)
- infof(data, " %s: %s\n", label, output);
+ infof(data, " %s: %s", label, output);
free((char *) output);
}
}
@@ -905,7 +906,7 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
if(len > 32)
elem.beg = q; /* Strip leading zero bytes. */
if(!certnum)
- infof(data, " RSA Public Key (%lu bits)\n", len);
+ infof(data, " RSA Public Key (%lu bits)", len);
if(data->set.ssl.certinfo) {
q = curl_maprintf("%lu", len);
if(q) {
@@ -978,7 +979,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
if(!certnum)
- infof(data, "%2d Subject: %s\n", certnum, ccp);
+ infof(data, "%2d Subject: %s", certnum, ccp);
free((char *) ccp);
/* Issuer. */
@@ -988,7 +989,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
if(!certnum)
- infof(data, " Issuer: %s\n", ccp);
+ infof(data, " Issuer: %s", ccp);
free((char *) ccp);
/* Version (always fits in less than 32 bits). */
@@ -1003,7 +1004,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
free((char *) ccp);
}
if(!certnum)
- infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
+ infof(data, " Version: %lu (0x%lx)", version + 1, version);
/* Serial number. */
ccp = ASN1tostr(&cert.serialNumber, 0);
@@ -1012,7 +1013,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
if(!certnum)
- infof(data, " Serial Number: %s\n", ccp);
+ infof(data, " Serial Number: %s", ccp);
free((char *) ccp);
/* Signature algorithm .*/
@@ -1023,7 +1024,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
if(!certnum)
- infof(data, " Signature Algorithm: %s\n", ccp);
+ infof(data, " Signature Algorithm: %s", ccp);
free((char *) ccp);
/* Start Date. */
@@ -1033,7 +1034,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
if(!certnum)
- infof(data, " Start Date: %s\n", ccp);
+ infof(data, " Start Date: %s", ccp);
free((char *) ccp);
/* Expire Date. */
@@ -1043,7 +1044,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
if(!certnum)
- infof(data, " Expire Date: %s\n", ccp);
+ infof(data, " Expire Date: %s", ccp);
free((char *) ccp);
/* Public Key Algorithm. */
@@ -1054,7 +1055,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
if(!certnum)
- infof(data, " Public Key Algorithm: %s\n", ccp);
+ infof(data, " Public Key Algorithm: %s", ccp);
do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
free((char *) ccp);
@@ -1065,7 +1066,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
if(!certnum)
- infof(data, " Signature: %s\n", ccp);
+ infof(data, " Signature: %s", ccp);
free((char *) ccp);
/* Generate PEM certificate. */
@@ -1098,12 +1099,13 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
if(data->set.ssl.certinfo)
Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
if(!certnum)
- infof(data, "%s\n", cp2);
+ infof(data, "%s", cp2);
free(cp2);
return CURLE_OK;
}
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL
+ * or USE_SECTRANSP */
#if defined(USE_GSKIT)
@@ -1220,12 +1222,12 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
switch(matched) {
case 1:
/* an alternative name matched the server hostname */
- infof(data, "\t subjectAltName: %s matched\n", dispname);
+ infof(data, " subjectAltName: %s matched", dispname);
return CURLE_OK;
case 0:
/* an alternative name field existed, but didn't match and then
we MUST fail */
- infof(data, "\t subjectAltName does not match %s\n", dispname);
+ infof(data, " subjectAltName does not match %s", dispname);
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1262,7 +1264,7 @@ CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
failf(data, "SSL: illegal cert name field");
else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
- infof(data, "\t common name: %s (matched)\n", dnsname);
+ infof(data, " common name: %s (matched)", dnsname);
free(dnsname);
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/x509asn1.h b/Utilities/cmcurl/lib/x509asn1.h
index 326e32d58..3b51eeef8 100644
--- a/Utilities/cmcurl/lib/x509asn1.h
+++ b/Utilities/cmcurl/lib/x509asn1.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \
- defined(USE_WOLFSSL) || defined(USE_SCHANNEL)
+ defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP)
#include "urldata.h"
@@ -129,5 +129,6 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
const char *beg, const char *end);
CURLcode Curl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
const char *beg, const char *end);
-#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL */
+#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL
+ * or USE_SECTRANSP */
#endif /* HEADER_CURL_X509ASN1_H */
diff --git a/Utilities/cmelf/elf32.h b/Utilities/cmelf/elf32.h
new file mode 100644
index 000000000..20d2ec254
--- /dev/null
+++ b/Utilities/cmelf/elf32.h
@@ -0,0 +1,265 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_ELF32_H_
+#define _SYS_ELF32_H_ 1
+
+#include "elf_common.h"
+
+/*
+ * ELF definitions common to all 32-bit architectures.
+ */
+
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+typedef uint64_t Elf32_Lword;
+
+typedef Elf32_Word Elf32_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf32_Word Elf32_Size;
+typedef Elf32_Sword Elf32_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf32_Half e_type; /* File type. */
+ Elf32_Half e_machine; /* Machine architecture. */
+ Elf32_Word e_version; /* ELF format version. */
+ Elf32_Addr e_entry; /* Entry point. */
+ Elf32_Off e_phoff; /* Program header file offset. */
+ Elf32_Off e_shoff; /* Section header file offset. */
+ Elf32_Word e_flags; /* Architecture-specific flags. */
+ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf32_Half e_phentsize; /* Size of program header entry. */
+ Elf32_Half e_phnum; /* Number of program header entries. */
+ Elf32_Half e_shentsize; /* Size of section header entry. */
+ Elf32_Half e_shnum; /* Number of section header entries. */
+ Elf32_Half e_shstrndx; /* Section name strings section. */
+} Elf32_Ehdr;
+
+/*
+ * Shared object information, found in SHT_MIPS_LIBLIST.
+ */
+
+typedef struct {
+ Elf32_Word l_name; /* The name of a shared object. */
+ Elf32_Word l_time_stamp; /* 32-bit timestamp. */
+ Elf32_Word l_checksum; /* Checksum of visible symbols, sizes. */
+ Elf32_Word l_version; /* Interface version string index. */
+ Elf32_Word l_flags; /* Flags (LL_*). */
+} Elf32_Lib;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+ Elf32_Word sh_name; /* Section name (index into the
+ section header string table). */
+ Elf32_Word sh_type; /* Section type. */
+ Elf32_Word sh_flags; /* Section flags. */
+ Elf32_Addr sh_addr; /* Address in memory image. */
+ Elf32_Off sh_offset; /* Offset in file. */
+ Elf32_Word sh_size; /* Size in bytes. */
+ Elf32_Word sh_link; /* Index of a related section. */
+ Elf32_Word sh_info; /* Depends on section type. */
+ Elf32_Word sh_addralign; /* Alignment in bytes. */
+ Elf32_Word sh_entsize; /* Size of each entry in section. */
+} Elf32_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+ Elf32_Word p_type; /* Entry type. */
+ Elf32_Off p_offset; /* File offset of contents. */
+ Elf32_Addr p_vaddr; /* Virtual address in memory image. */
+ Elf32_Addr p_paddr; /* Physical address (not used). */
+ Elf32_Word p_filesz; /* Size of contents in file. */
+ Elf32_Word p_memsz; /* Size of contents in memory. */
+ Elf32_Word p_flags; /* Access permission flags. */
+ Elf32_Word p_align; /* Alignment in memory and file. */
+} Elf32_Phdr;
+
+/*
+ * Dynamic structure. The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+ Elf32_Sword d_tag; /* Entry type. */
+ union {
+ Elf32_Word d_val; /* Integer value. */
+ Elf32_Addr d_ptr; /* Address value. */
+ } d_un;
+} Elf32_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Relocation type and symbol index. */
+} Elf32_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Relocation type and symbol index. */
+ Elf32_Sword r_addend; /* Addend. */
+} Elf32_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF32_R_SYM(info) ((info) >> 8)
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+
+/* Macro for constructing r_info from field values. */
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+
+/*
+ * Note entry header
+ */
+typedef Elf_Note Elf32_Nhdr;
+
+/*
+ * Move entry
+ */
+typedef struct {
+ Elf32_Lword m_value; /* symbol value */
+ Elf32_Word m_info; /* size + index */
+ Elf32_Word m_poffset; /* symbol offset */
+ Elf32_Half m_repeat; /* repeat count */
+ Elf32_Half m_stride; /* stride info */
+} Elf32_Move;
+
+/*
+ * The macros compose and decompose values for Move.r_info
+ *
+ * sym = ELF32_M_SYM(M.m_info)
+ * size = ELF32_M_SIZE(M.m_info)
+ * M.m_info = ELF32_M_INFO(sym, size)
+ */
+#define ELF32_M_SYM(info) ((info)>>8)
+#define ELF32_M_SIZE(info) ((unsigned char)(info))
+#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ * Hardware/Software capabilities entry
+ */
+typedef struct {
+ Elf32_Word c_tag; /* how to interpret value */
+ union {
+ Elf32_Word c_val;
+ Elf32_Addr c_ptr;
+ } c_un;
+} Elf32_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+ Elf32_Word st_name; /* String table index of name. */
+ Elf32_Addr st_value; /* Symbol value. */
+ Elf32_Word st_size; /* Size of associated object. */
+ unsigned char st_info; /* Type and binding information. */
+ unsigned char st_other; /* Reserved (not used). */
+ Elf32_Half st_shndx; /* Section index of symbol. */
+} Elf32_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF32_ST_BIND(info) ((info) >> 4)
+#define ELF32_ST_TYPE(info) ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
+
+/* Structures used by Sun & GNU symbol versioning. */
+typedef struct
+{
+ Elf32_Half vd_version;
+ Elf32_Half vd_flags;
+ Elf32_Half vd_ndx;
+ Elf32_Half vd_cnt;
+ Elf32_Word vd_hash;
+ Elf32_Word vd_aux;
+ Elf32_Word vd_next;
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf32_Word vda_name;
+ Elf32_Word vda_next;
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf32_Half vn_version;
+ Elf32_Half vn_cnt;
+ Elf32_Word vn_file;
+ Elf32_Word vn_aux;
+ Elf32_Word vn_next;
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf32_Word vna_hash;
+ Elf32_Half vna_flags;
+ Elf32_Half vna_other;
+ Elf32_Word vna_name;
+ Elf32_Word vna_next;
+} Elf32_Vernaux;
+
+typedef Elf32_Half Elf32_Versym;
+
+typedef struct {
+ Elf32_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf32_Half si_flags; /* per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct {
+ Elf32_Word ch_type;
+ Elf32_Word ch_size;
+ Elf32_Word ch_addralign;
+} Elf32_Chdr;
+
+#endif /* !_SYS_ELF32_H_ */
diff --git a/Utilities/cmelf/elf64.h b/Utilities/cmelf/elf64.h
new file mode 100644
index 000000000..6efe14716
--- /dev/null
+++ b/Utilities/cmelf/elf64.h
@@ -0,0 +1,269 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_ELF64_H_
+#define _SYS_ELF64_H_ 1
+
+#include "elf_common.h"
+
+/*
+ * ELF definitions common to all 64-bit architectures.
+ */
+
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef uint64_t Elf64_Off;
+typedef int32_t Elf64_Sword;
+typedef int64_t Elf64_Sxword;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Lword;
+typedef uint64_t Elf64_Xword;
+
+/*
+ * Types of dynamic symbol hash table bucket and chain elements.
+ *
+ * This is inconsistent among 64 bit architectures, so a machine dependent
+ * typedef is required.
+ */
+
+typedef Elf64_Word Elf64_Hashelt;
+
+/* Non-standard class-dependent datatype used for abstraction. */
+typedef Elf64_Xword Elf64_Size;
+typedef Elf64_Sxword Elf64_Ssize;
+
+/*
+ * ELF header.
+ */
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* File identification. */
+ Elf64_Half e_type; /* File type. */
+ Elf64_Half e_machine; /* Machine architecture. */
+ Elf64_Word e_version; /* ELF format version. */
+ Elf64_Addr e_entry; /* Entry point. */
+ Elf64_Off e_phoff; /* Program header file offset. */
+ Elf64_Off e_shoff; /* Section header file offset. */
+ Elf64_Word e_flags; /* Architecture-specific flags. */
+ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name strings section. */
+} Elf64_Ehdr;
+
+/*
+ * Shared object information, found in SHT_MIPS_LIBLIST.
+ */
+
+typedef struct {
+ Elf64_Word l_name; /* The name of a shared object. */
+ Elf64_Word l_time_stamp; /* 64-bit timestamp. */
+ Elf64_Word l_checksum; /* Checksum of visible symbols, sizes. */
+ Elf64_Word l_version; /* Interface version string index. */
+ Elf64_Word l_flags; /* Flags (LL_*). */
+} Elf64_Lib;
+
+/*
+ * Section header.
+ */
+
+typedef struct {
+ Elf64_Word sh_name; /* Section name (index into the
+ section header string table). */
+ Elf64_Word sh_type; /* Section type. */
+ Elf64_Xword sh_flags; /* Section flags. */
+ Elf64_Addr sh_addr; /* Address in memory image. */
+ Elf64_Off sh_offset; /* Offset in file. */
+ Elf64_Xword sh_size; /* Size in bytes. */
+ Elf64_Word sh_link; /* Index of a related section. */
+ Elf64_Word sh_info; /* Depends on section type. */
+ Elf64_Xword sh_addralign; /* Alignment in bytes. */
+ Elf64_Xword sh_entsize; /* Size of each entry in section. */
+} Elf64_Shdr;
+
+/*
+ * Program header.
+ */
+
+typedef struct {
+ Elf64_Word p_type; /* Entry type. */
+ Elf64_Word p_flags; /* Access permission flags. */
+ Elf64_Off p_offset; /* File offset of contents. */
+ Elf64_Addr p_vaddr; /* Virtual address in memory image. */
+ Elf64_Addr p_paddr; /* Physical address (not used). */
+ Elf64_Xword p_filesz; /* Size of contents in file. */
+ Elf64_Xword p_memsz; /* Size of contents in memory. */
+ Elf64_Xword p_align; /* Alignment in memory and file. */
+} Elf64_Phdr;
+
+/*
+ * Dynamic structure. The ".dynamic" section contains an array of them.
+ */
+
+typedef struct {
+ Elf64_Sxword d_tag; /* Entry type. */
+ union {
+ Elf64_Xword d_val; /* Integer value. */
+ Elf64_Addr d_ptr; /* Address value. */
+ } d_un;
+} Elf64_Dyn;
+
+/*
+ * Relocation entries.
+ */
+
+/* Relocations that don't need an addend field. */
+typedef struct {
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Relocation type and symbol index. */
+} Elf64_Rel;
+
+/* Relocations that need an addend field. */
+typedef struct {
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Relocation type and symbol index. */
+ Elf64_Sxword r_addend; /* Addend. */
+} Elf64_Rela;
+
+/* Macros for accessing the fields of r_info. */
+#define ELF64_R_SYM(info) ((info) >> 32)
+#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
+
+/* Macro for constructing r_info from field values. */
+#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
+
+#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40)
+#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56)
+#define ELF64_R_TYPE_INFO(data, type) \
+ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type))
+
+/*
+ * Note entry header
+ */
+typedef Elf_Note Elf64_Nhdr;
+
+/*
+ * Move entry
+ */
+typedef struct {
+ Elf64_Lword m_value; /* symbol value */
+ Elf64_Xword m_info; /* size + index */
+ Elf64_Xword m_poffset; /* symbol offset */
+ Elf64_Half m_repeat; /* repeat count */
+ Elf64_Half m_stride; /* stride info */
+} Elf64_Move;
+
+#define ELF64_M_SYM(info) ((info)>>8)
+#define ELF64_M_SIZE(info) ((unsigned char)(info))
+#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size))
+
+/*
+ * Hardware/Software capabilities entry
+ */
+typedef struct {
+ Elf64_Xword c_tag; /* how to interpret value */
+ union {
+ Elf64_Xword c_val;
+ Elf64_Addr c_ptr;
+ } c_un;
+} Elf64_Cap;
+
+/*
+ * Symbol table entries.
+ */
+
+typedef struct {
+ Elf64_Word st_name; /* String table index of name. */
+ unsigned char st_info; /* Type and binding information. */
+ unsigned char st_other; /* Reserved (not used). */
+ Elf64_Half st_shndx; /* Section index of symbol. */
+ Elf64_Addr st_value; /* Symbol value. */
+ Elf64_Xword st_size; /* Size of associated object. */
+} Elf64_Sym;
+
+/* Macros for accessing the fields of st_info. */
+#define ELF64_ST_BIND(info) ((info) >> 4)
+#define ELF64_ST_TYPE(info) ((info) & 0xf)
+
+/* Macro for constructing st_info from field values. */
+#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Macro for accessing the fields of st_other. */
+#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
+
+/* Structures used by Sun & GNU-style symbol versioning. */
+typedef struct {
+ Elf64_Half vd_version;
+ Elf64_Half vd_flags;
+ Elf64_Half vd_ndx;
+ Elf64_Half vd_cnt;
+ Elf64_Word vd_hash;
+ Elf64_Word vd_aux;
+ Elf64_Word vd_next;
+} Elf64_Verdef;
+
+typedef struct {
+ Elf64_Word vda_name;
+ Elf64_Word vda_next;
+} Elf64_Verdaux;
+
+typedef struct {
+ Elf64_Half vn_version;
+ Elf64_Half vn_cnt;
+ Elf64_Word vn_file;
+ Elf64_Word vn_aux;
+ Elf64_Word vn_next;
+} Elf64_Verneed;
+
+typedef struct {
+ Elf64_Word vna_hash;
+ Elf64_Half vna_flags;
+ Elf64_Half vna_other;
+ Elf64_Word vna_name;
+ Elf64_Word vna_next;
+} Elf64_Vernaux;
+
+typedef Elf64_Half Elf64_Versym;
+
+typedef struct {
+ Elf64_Half si_boundto; /* direct bindings - symbol bound to */
+ Elf64_Half si_flags; /* per symbol flags */
+} Elf64_Syminfo;
+
+typedef struct {
+ Elf64_Word ch_type;
+ Elf64_Word ch_reserved;
+ Elf64_Xword ch_size;
+ Elf64_Xword ch_addralign;
+} Elf64_Chdr;
+
+#endif /* !_SYS_ELF64_H_ */
diff --git a/Utilities/cmelf/elf_common.h b/Utilities/cmelf/elf_common.h
new file mode 100644
index 000000000..395c45b58
--- /dev/null
+++ b/Utilities/cmelf/elf_common.h
@@ -0,0 +1,1492 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2017, 2018 Dell EMC
+ * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien
+ * Copyright (c) 1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_ELF_COMMON_H_
+#define _SYS_ELF_COMMON_H_ 1
+
+/*
+ * ELF definitions that are independent of architecture or word size.
+ */
+
+/*
+ * Note header. The ".note" section contains an array of notes. Each
+ * begins with this header, aligned to a word boundary. Immediately
+ * following the note header is n_namesz bytes of name, padded to the
+ * next word boundary. Then comes n_descsz bytes of descriptor, again
+ * padded to a word boundary. The values of n_namesz and n_descsz do
+ * not include the padding.
+ */
+
+#ifndef LOCORE
+typedef struct {
+ uint32_t n_namesz; /* Length of name. */
+ uint32_t n_descsz; /* Length of descriptor. */
+ uint32_t n_type; /* Type of this note. */
+} Elf_Note;
+typedef Elf_Note Elf_Nhdr;
+#endif
+
+/*
+ * Option kinds.
+ */
+#define ODK_NULL 0 /* undefined */
+#define ODK_REGINFO 1 /* register usage info */
+#define ODK_EXCEPTIONS 2 /* exception processing info */
+#define ODK_PAD 3 /* section padding */
+#define ODK_HWPATCH 4 /* hardware patch applied */
+#define ODK_FILL 5 /* fill value used by the linker */
+#define ODK_TAGS 6 /* reserved space for tools */
+#define ODK_HWAND 7 /* hardware AND patch applied */
+#define ODK_HWOR 8 /* hardware OR patch applied */
+#define ODK_GP_GROUP 9 /* GP group for text/data sections */
+#define ODK_IDENT 10 /* ID information */
+#define ODK_PAGESIZE 11 /* page size information */
+
+/*
+ * ODK_EXCEPTIONS info field masks.
+ */
+#define OEX_FPU_MIN 0x0000001f /* min FPU exception required */
+#define OEX_FPU_MAX 0x00001f00 /* max FPU exception allowed */
+#define OEX_PAGE0 0x00010000 /* page zero must be mapped */
+#define OEX_SMM 0x00020000 /* run in sequential memory mode */
+#define OEX_PRECISEFP 0x00040000 /* run in precise FP exception mode */
+#define OEX_DISMISS 0x00080000 /* dismiss invalid address traps */
+
+/*
+ * ODK_PAD info field masks.
+ */
+#define OPAD_PREFIX 0x0001
+#define OPAD_POSTFIX 0x0002
+#define OPAD_SYMBOL 0x0004
+
+/*
+ * ODK_HWPATCH info field masks.
+ */
+#define OHW_R4KEOP 0x00000001 /* patch for R4000 branch at end-of-page bug */
+#define OHW_R8KPFETCH 0x00000002 /* R8000 prefetch bug may occur */
+#define OHW_R5KEOP 0x00000004 /* patch for R5000 branch at end-of-page bug */
+#define OHW_R5KCVTL 0x00000008 /* R5000 cvt.[ds].l bug: clean == 1 */
+#define OHW_R10KLDL 0x00000010UL /* need patch for R10000 misaligned load */
+
+/*
+ * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks.
+ */
+#define OHWA0_R4KEOP_CHECKED 0x00000001 /* object checked for R4000 end-of-page bug */
+#define OHWA0_R4KEOP_CLEAN 0x00000002 /* object verified clean for R4000 end-of-page bug */
+#define OHWO0_FIXADE 0x00000001 /* object requires call to fixade */
+
+/*
+ * ODK_IDENT/ODK_GP_GROUP info field masks.
+ */
+#define OGP_GROUP 0x0000ffff /* GP group number */
+#define OGP_SELF 0x00010000 /* GP group is self-contained */
+
+/*
+ * The header for GNU-style hash sections.
+ */
+
+#ifndef LOCORE
+typedef struct {
+ uint32_t gh_nbuckets; /* Number of hash buckets. */
+ uint32_t gh_symndx; /* First visible symbol in .dynsym. */
+ uint32_t gh_maskwords; /* #maskwords used in bloom filter. */
+ uint32_t gh_shift2; /* Bloom filter shift count. */
+} Elf_GNU_Hash_Header;
+#endif
+
+/* Indexes into the e_ident array. Keep synced with
+ http://www.sco.com/developers/gabi/latest/ch4.eheader.html */
+#define EI_MAG0 0 /* Magic number, byte 0. */
+#define EI_MAG1 1 /* Magic number, byte 1. */
+#define EI_MAG2 2 /* Magic number, byte 2. */
+#define EI_MAG3 3 /* Magic number, byte 3. */
+#define EI_CLASS 4 /* Class of machine. */
+#define EI_DATA 5 /* Data format. */
+#define EI_VERSION 6 /* ELF format version. */
+#define EI_OSABI 7 /* Operating system / ABI identification */
+#define EI_ABIVERSION 8 /* ABI version */
+#define OLD_EI_BRAND 8 /* Start of architecture identification. */
+#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for the magic number bytes. */
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF" /* magic string */
+#define SELFMAG 4 /* magic string size */
+
+/* Values for e_ident[EI_VERSION] and e_version. */
+#define EV_NONE 0
+#define EV_CURRENT 1
+
+/* Values for e_ident[EI_CLASS]. */
+#define ELFCLASSNONE 0 /* Unknown class. */
+#define ELFCLASS32 1 /* 32-bit architecture. */
+#define ELFCLASS64 2 /* 64-bit architecture. */
+
+/* Values for e_ident[EI_DATA]. */
+#define ELFDATANONE 0 /* Unknown data format. */
+#define ELFDATA2LSB 1 /* 2's complement little-endian. */
+#define ELFDATA2MSB 2 /* 2's complement big-endian. */
+
+/* Values for e_ident[EI_OSABI]. */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_AIX 7 /* AIX */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_OPENVMS 13 /* Open VMS */
+#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_AROS 15 /* Amiga Research OS */
+#define ELFOSABI_FENIXOS 16 /* FenixOS */
+#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */
+#define ELFOSABI_OPENVOS 18 /* Stratus Technologies OpenVOS */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
+#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
+#define ELFOSABI_GNU ELFOSABI_LINUX
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* Values for e_type. */
+#define ET_NONE 0 /* Unknown type. */
+#define ET_REL 1 /* Relocatable. */
+#define ET_EXEC 2 /* Executable. */
+#define ET_DYN 3 /* Shared object. */
+#define ET_CORE 4 /* Core file. */
+#define ET_LOOS 0xfe00 /* First operating system specific. */
+#define ET_HIOS 0xfeff /* Last operating system-specific. */
+#define ET_LOPROC 0xff00 /* First processor-specific. */
+#define ET_HIPROC 0xffff /* Last processor-specific. */
+
+/* Values for e_machine. */
+#define EM_NONE 0 /* Unknown machine. */
+#define EM_M32 1 /* AT&T WE32100. */
+#define EM_SPARC 2 /* Sun SPARC. */
+#define EM_386 3 /* Intel i386. */
+#define EM_68K 4 /* Motorola 68000. */
+#define EM_88K 5 /* Motorola 88000. */
+#define EM_IAMCU 6 /* Intel MCU. */
+#define EM_860 7 /* Intel i860. */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
+#define EM_S370 9 /* IBM System/370. */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
+#define EM_PARISC 15 /* HP PA-RISC. */
+#define EM_VPP500 17 /* Fujitsu VPP500. */
+#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
+#define EM_960 19 /* Intel 80960. */
+#define EM_PPC 20 /* PowerPC 32-bit. */
+#define EM_PPC64 21 /* PowerPC 64-bit. */
+#define EM_S390 22 /* IBM System/390. */
+#define EM_V800 36 /* NEC V800. */
+#define EM_FR20 37 /* Fujitsu FR20. */
+#define EM_RH32 38 /* TRW RH-32. */
+#define EM_RCE 39 /* Motorola RCE. */
+#define EM_ARM 40 /* ARM. */
+#define EM_SH 42 /* Hitachi SH. */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
+#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
+#define EM_ARC 45 /* Argonaut RISC Core. */
+#define EM_H8_300 46 /* Hitachi H8/300. */
+#define EM_H8_300H 47 /* Hitachi H8/300H. */
+#define EM_H8S 48 /* Hitachi H8S. */
+#define EM_H8_500 49 /* Hitachi H8/500. */
+#define EM_IA_64 50 /* Intel IA-64 Processor. */
+#define EM_MIPS_X 51 /* Stanford MIPS-X. */
+#define EM_COLDFIRE 52 /* Motorola ColdFire. */
+#define EM_68HC12 53 /* Motorola M68HC12. */
+#define EM_MMA 54 /* Fujitsu MMA. */
+#define EM_PCP 55 /* Siemens PCP. */
+#define EM_NCPU 56 /* Sony nCPU. */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
+#define EM_STARCORE 58 /* Motorola Star*Core processor. */
+#define EM_ME16 59 /* Toyota ME16 processor. */
+#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
+#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
+#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
+#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_PDSP 63 /* Sony DSP Processor. */
+#define EM_FX66 66 /* Siemens FX66 microcontroller. */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16
+ microcontroller. */
+#define EM_ST7 68 /* STmicroelectronics ST7 8-bit
+ microcontroller. */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */
+#define EM_SVX 73 /* Silicon Graphics SVx. */
+#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */
+#define EM_VAX 75 /* Digital VAX. */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded
+ processor. */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded
+ processor. */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */
+#define EM_HUANY 81 /* Harvard University machine-independent
+ object files. */
+#define EM_PRISM 82 /* SiTera Prism. */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */
+#define EM_FR30 84 /* Fujitsu FR30. */
+#define EM_D10V 85 /* Mitsubishi D10V. */
+#define EM_D30V 86 /* Mitsubishi D30V. */
+#define EM_V850 87 /* NEC v850. */
+#define EM_M32R 88 /* Mitsubishi M32R. */
+#define EM_MN10300 89 /* Matsushita MN10300. */
+#define EM_MN10200 90 /* Matsushita MN10200. */
+#define EM_PJ 91 /* picoJava. */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */
+#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose
+ Processor. */
+#define EM_NS32K 97 /* National Semiconductor 32000 series. */
+#define EM_TPC 98 /* Tenor Network TPC processor. */
+#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */
+#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */
+#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */
+#define EM_MAX 102 /* MAX Processor. */
+#define EM_CR 103 /* National Semiconductor CompactRISC
+ microprocessor. */
+#define EM_F2MC16 104 /* Fujitsu F2MC16. */
+#define EM_MSP430 105 /* Texas Instruments embedded microcontroller
+ msp430. */
+#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */
+#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */
+#define EM_SEP 108 /* Sharp embedded microprocessor. */
+#define EM_ARCA 109 /* Arca RISC Microprocessor. */
+#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd.
+ and MPRC of Peking University */
+#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */
+#define EM_RISCV 243 /* RISC-V */
+
+/* Non-standard or deprecated. */
+#define EM_486 6 /* Intel i486. */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
+#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
+
+/**
+ * e_flags
+ */
+#define EF_ARM_RELEXEC 0x1
+#define EF_ARM_HASENTRY 0x2
+#define EF_ARM_SYMSARESORTED 0x4
+#define EF_ARM_DYNSYMSUSESEGIDX 0x8
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_LE8 0x00400000
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_EABIMASK 0xFF000000
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+#define EF_ARM_INTERWORK 0x00000004
+#define EF_ARM_APCS_26 0x00000008
+#define EF_ARM_APCS_FLOAT 0x00000010
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
+#define EF_ARM_SOFT_FLOAT EF_ARM_ABI_FLOAT_SOFT /* Pre-V5 ABI name */
+#define EF_ARM_ABI_FLOAT_HARD 0x00000400
+#define EF_ARM_VFP_FLOAT EF_ARM_ABI_FLOAT_HARD /* Pre-V5 ABI name */
+#define EF_ARM_MAVERICK_FLOAT 0x00000800
+
+#define EF_MIPS_NOREORDER 0x00000001
+#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
+#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */
+#define EF_MIPS_UCODE 0x00000010
+#define EF_MIPS_ABI2 0x00000020 /* N32 */
+#define EF_MIPS_OPTIONS_FIRST 0x00000080
+#define EF_MIPS_ABI 0x0000F000
+#define EF_MIPS_ABI_O32 0x00001000
+#define EF_MIPS_ABI_O64 0x00002000
+#define EF_MIPS_ABI_EABI32 0x00003000
+#define EF_MIPS_ABI_EABI64 0x00004000
+#define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */
+#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */
+#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */
+#define EF_MIPS_ARCH 0xF0000000 /* Architecture field */
+#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */
+#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */
+#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */
+#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code */
+#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code */
+#define EF_MIPS_ARCH_32 0x50000000 /* -mips32 code */
+#define EF_MIPS_ARCH_64 0x60000000 /* -mips64 code */
+#define EF_MIPS_ARCH_32R2 0x70000000 /* -mips32r2 code */
+#define EF_MIPS_ARCH_64R2 0x80000000 /* -mips64r2 code */
+
+#define EF_PPC_EMB 0x80000000
+#define EF_PPC_RELOCATABLE 0x00010000
+#define EF_PPC_RELOCATABLE_LIB 0x00008000
+
+#define EF_RISCV_RVC 0x00000001
+#define EF_RISCV_FLOAT_ABI_MASK 0x00000006
+#define EF_RISCV_FLOAT_ABI_SOFT 0x00000000
+#define EF_RISCV_FLOAT_ABI_SINGLE 0x000002
+#define EF_RISCV_FLOAT_ABI_DOUBLE 0x000004
+#define EF_RISCV_FLOAT_ABI_QUAD 0x00000006
+#define EF_RISCV_RVE 0x00000008
+#define EF_RISCV_TSO 0x00000010
+
+#define EF_SPARC_EXT_MASK 0x00ffff00
+#define EF_SPARC_32PLUS 0x00000100
+#define EF_SPARC_SUN_US1 0x00000200
+#define EF_SPARC_HAL_R1 0x00000200
+#define EF_SPARC_SUN_US3 0x00000800
+
+#define EF_SPARCV9_MM 0x00000003
+#define EF_SPARCV9_TSO 0x00000000
+#define EF_SPARCV9_PSO 0x00000001
+#define EF_SPARCV9_RMO 0x00000002
+
+/* Special section indexes. */
+#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
+#define SHN_LORESERVE 0xff00 /* First of reserved range. */
+#define SHN_LOPROC 0xff00 /* First processor-specific. */
+#define SHN_HIPROC 0xff1f /* Last processor-specific. */
+#define SHN_LOOS 0xff20 /* First operating system-specific. */
+#define SHN_FBSD_CACHED SHN_LOOS /* Transient, for sys/kern/link_elf_obj
+ linker only: Cached global in local
+ symtab. */
+#define SHN_HIOS 0xff3f /* Last operating system-specific. */
+#define SHN_ABS 0xfff1 /* Absolute values. */
+#define SHN_COMMON 0xfff2 /* Common data. */
+#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
+#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends */
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relocation section - no addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
+#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
+#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
+#define SHT_GROUP 17 /* Section group. */
+#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
+#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
+#define SHT_LOSUNW 0x6ffffff4
+#define SHT_SUNW_dof 0x6ffffff4
+#define SHT_SUNW_cap 0x6ffffff5
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5
+#define SHT_SUNW_SIGNATURE 0x6ffffff6
+#define SHT_GNU_HASH 0x6ffffff6
+#define SHT_GNU_LIBLIST 0x6ffffff7
+#define SHT_SUNW_ANNOTATE 0x6ffffff7
+#define SHT_SUNW_DEBUGSTR 0x6ffffff8
+#define SHT_SUNW_DEBUG 0x6ffffff9
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_SUNW_verdef 0x6ffffffd
+#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */
+#define SHT_SUNW_verneed 0x6ffffffe
+#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */
+#define SHT_SUNW_versym 0x6fffffff
+#define SHT_GNU_versym 0x6fffffff /* Symbol version table */
+#define SHT_HISUNW 0x6fffffff
+#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_X86_64_UNWIND 0x70000001 /* unwind information */
+#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND
+
+#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */
+#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking
+ pre-emption map. */
+#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility
+ attributes. */
+#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */
+#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */
+#define SHT_MIPS_LIBLIST 0x70000000
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002
+#define SHT_MIPS_GPTAB 0x70000003
+#define SHT_MIPS_UCODE 0x70000004
+#define SHT_MIPS_DEBUG 0x70000005
+#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
+#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
+#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+#define SHT_MIPS_ABIFLAGS 0x7000002a
+
+#define SHT_SPARC_GOTDATA 0x70000000
+
+#define SHTORDERED
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Flags for sh_flags. */
+#define SHF_WRITE 0x1 /* Section contains writable data. */
+#define SHF_ALLOC 0x2 /* Section occupies memory. */
+#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
+#define SHF_MERGE 0x10 /* Section may be merged. */
+#define SHF_STRINGS 0x20 /* Section contains strings. */
+#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
+#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
+#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
+#define SHF_GROUP 0x200 /* Member of section group. */
+#define SHF_TLS 0x400 /* Section contains TLS data. */
+#define SHF_COMPRESSED 0x800 /* Section contains compressed data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
+
+/* Flags for section groups. */
+#define GRP_COMDAT 0x1 /* COMDAT semantics. */
+
+/*
+ * Flags / mask for .gnu.versym sections.
+ */
+#define VERSYM_VERSION 0x7fff
+#define VERSYM_HIDDEN 0x8000
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+#define PT_TLS 7 /* Thread local storage segment */
+#define PT_LOOS 0x60000000 /* First OS-specific. */
+#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */
+#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_GNU_STACK 0x6474e551
+#define PT_GNU_RELRO 0x6474e552
+#define PT_DUMP_DELTA 0x6fb5d000 /* va->pa map for kernel dumps
+ (currently arm). */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */
+#define PT_SUNWDTRACE 0x6ffffffc /* private */
+#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* Last OS-specific. */
+#define PT_LOPROC 0x70000000 /* First processor-specific type. */
+#define PT_ARM_ARCHEXT 0x70000000 /* ARM arch compat information. */
+#define PT_ARM_EXIDX 0x70000001 /* ARM exception unwind tables. */
+#define PT_MIPS_REGINFO 0x70000000 /* MIPS register usage info */
+#define PT_MIPS_RTPROC 0x70000001 /* MIPS runtime procedure tbl */
+#define PT_MIPS_OPTIONS 0x70000002 /* MIPS e_flags value*/
+#define PT_MIPS_ABIFLAGS 0x70000003 /* MIPS fp mode */
+#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+#define PT_OPENBSD_RANDOMIZE 0x65A3DBE6 /* OpenBSD random data segment */
+#define PT_OPENBSD_WXNEEDED 0x65A3DBE7 /* OpenBSD EXEC/WRITE pages needed */
+#define PT_OPENBSD_BOOTDATA 0x65A41BE6 /* OpenBSD section for boot args */
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
+
+/* Extended program header index. */
+#define PN_XNUM 0xffff
+
+/* Values for d_tag. */
+#define DT_NULL 0 /* Terminating entry. */
+#define DT_NEEDED 1 /* String table offset of a needed shared
+ library. */
+#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT 3 /* Processor-dependent address. */
+#define DT_HASH 4 /* Address of symbol hash table. */
+#define DT_STRTAB 5 /* Address of string table. */
+#define DT_SYMTAB 6 /* Address of symbol table. */
+#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ 10 /* Size of string table. */
+#define DT_SYMENT 11 /* Size of each symbol table entry. */
+#define DT_INIT 12 /* Address of initialization function. */
+#define DT_FINI 13 /* Address of finalization function. */
+#define DT_SONAME 14 /* String table offset of shared object
+ name. */
+#define DT_RPATH 15 /* String table offset of library path. [sup] */
+#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
+#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL 20 /* Type of relocation used for PLT. */
+#define DT_DEBUG 21 /* Reserved (not used). */
+#define DT_TEXTREL 22 /* Indicates there may be relocations in
+ non-writable segments. [sup] */
+#define DT_JMPREL 23 /* Address of PLT relocations. */
+#define DT_BIND_NOW 24 /* [sup] */
+#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
+ initialization functions */
+#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
+ termination functions */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
+ initialization functions. */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
+ termination functions. */
+#define DT_RUNPATH 29 /* String table offset of a null-terminated
+ library search path string. */
+#define DT_FLAGS 30 /* Object specific flag values. */
+#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
+ and less than DT_LOOS follow the rules for
+ the interpretation of the d_un union
+ as follows: even == 'd_ptr', odd == 'd_val'
+ or none */
+#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
+ pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
+ pre-initialization functions. */
+#define DT_MAXPOSTAGS 34 /* number of positive tags */
+#define DT_LOOS 0x6000000d /* First OS-specific */
+#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */
+#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */
+#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */
+#define DT_SUNW_CAP 0x60000010 /* hardware/software */
+#define DT_SUNW_ASLR 0x60000023 /* ASLR control */
+#define DT_HIOS 0x6ffff000 /* Last OS-specific */
+
+/*
+ * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ * Dyn.d_un.d_val field of the Elf*_Dyn structure.
+ */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list */
+#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
+#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
+#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
+#define DT_MOVESZ 0x6ffffdfb /* move table size */
+#define DT_FEATURE 0x6ffffdfc /* feature holder */
+#define DT_FEATURE_1 DT_FEATURE
+#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */
+ /* the following DT_* entry. */
+ /* See DF_P1_* definitions */
+#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */
+#define DT_VALRNGHI 0x6ffffdff
+
+/*
+ * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ * Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+ *
+ * If any adjustment is made to the ELF object after it has been
+ * built, these entries will need to be adjusted.
+ */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */
+#define DT_TLSDESC_PLT 0x6ffffef6 /* loc. of PLT for tlsdesc resolver */
+#define DT_TLSDESC_GOT 0x6ffffef7 /* loc. of GOT for tlsdesc resolver */
+#define DT_GNU_CONFLICT 0x6ffffef8 /* address of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* address of library list */
+#define DT_CONFIG 0x6ffffefa /* configuration information */
+#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
+#define DT_AUDIT 0x6ffffefc /* object auditing */
+#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */
+#define DT_MOVETAB 0x6ffffefe /* move table */
+#define DT_SYMINFO 0x6ffffeff /* syminfo table */
+#define DT_ADDRRNGHI 0x6ffffeff
+
+#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */
+#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */
+#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */
+#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */
+#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */
+#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */
+
+#define DT_LOPROC 0x70000000 /* First processor-specific type. */
+
+#define DT_ARM_SYMTABSZ 0x70000001
+#define DT_ARM_PREEMPTMAP 0x70000002
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_DEPRECATED_SPARC_REGISTER 0x7000001
+
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016
+#define DT_MIPS_DELTA_CLASS 0x70000017
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018
+#define DT_MIPS_DELTA_INSTANCE 0x70000019
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001A
+#define DT_MIPS_DELTA_RELOC 0x7000001B
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001C
+#define DT_MIPS_DELTA_SYM 0x7000001D
+#define DT_MIPS_DELTA_SYM_NO 0x7000001E
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
+#define DT_MIPS_CXX_FLAGS 0x70000022
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029
+#define DT_MIPS_INTERFACE 0x7000002A
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002B
+#define DT_MIPS_INTERFACE_SIZE 0x7000002C
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002D
+#define DT_MIPS_PERF_SUFFIX 0x7000002E
+#define DT_MIPS_COMPACT_SIZE 0x7000002F
+#define DT_MIPS_GP_VALUE 0x70000030
+#define DT_MIPS_AUX_DYNAMIC 0x70000031
+#define DT_MIPS_PLTGOT 0x70000032
+#define DT_MIPS_RLD_OBJ_UPDATE 0x70000033
+#define DT_MIPS_RWPLT 0x70000034
+#define DT_MIPS_RLD_MAP_REL 0x70000035
+
+#define DT_PPC_GOT 0x70000000
+#define DT_PPC_TLSOPT 0x70000001
+
+#define DT_PPC64_GLINK 0x70000000
+#define DT_PPC64_OPD 0x70000001
+#define DT_PPC64_OPDSZ 0x70000002
+#define DT_PPC64_TLSOPT 0x70000003
+
+#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */
+#define DT_USED 0x7ffffffe /* ignored - same as needed */
+#define DT_FILTER 0x7fffffff /* shared library filter name */
+#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+/* Values for DT_FLAGS */
+#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
+ make reference to the $ORIGIN substitution
+ string */
+#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
+#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
+ non-writable segments. */
+#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
+ process all relocations for the object
+ containing this entry before transferring
+ control to the program. */
+#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
+ executable contains code using a static
+ thread-local storage scheme. */
+
+/* Values for DT_FLAGS_1 */
+#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */
+#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */
+#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */
+#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */
+#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */
+#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */
+#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */
+#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */
+#define DF_1_PIE 0x08000000 /* Is position-independent executable */
+
+/* Values for l_flags. */
+#define LL_NONE 0x0 /* no flags */
+#define LL_EXACT_MATCH 0x1 /* require an exact match */
+#define LL_IGNORE_INT_VER 0x2 /* ignore version incompatibilities */
+#define LL_REQUIRE_MINOR 0x4
+#define LL_EXPORTS 0x8
+#define LL_DELAY_LOAD 0x10
+#define LL_DELTA 0x20
+
+/* Note section names */
+#define ELF_NOTE_FREEBSD "FreeBSD"
+#define ELF_NOTE_NETBSD "NetBSD"
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+#define ELF_NOTE_GNU "GNU"
+
+/* Values for n_type used in executables. */
+#define NT_FREEBSD_ABI_TAG 1
+#define NT_FREEBSD_NOINIT_TAG 2
+#define NT_FREEBSD_ARCH_TAG 3
+#define NT_FREEBSD_FEATURE_CTL 4
+
+/* NT_FREEBSD_FEATURE_CTL desc[0] bits */
+#define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001
+#define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002
+#define NT_FREEBSD_FCTL_STKGAP_DISABLE 0x00000004
+#define NT_FREEBSD_FCTL_WXNEEDED 0x00000008
+#define NT_FREEBSD_FCTL_LA48 0x00000010
+#define NT_FREEBSD_FCTL_ASG_DISABLE 0x00000020 /* ASLR STACK GAP Disable */
+
+/* Values for n_type. Used in core files. */
+#define NT_PRSTATUS 1 /* Process status. */
+#define NT_FPREGSET 2 /* Floating point registers. */
+#define NT_PRPSINFO 3 /* Process state info. */
+#define NT_THRMISC 7 /* Thread miscellaneous info. */
+#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */
+#define NT_PROCSTAT_FILES 9 /* Procstat files data. */
+#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */
+#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */
+#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */
+#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */
+#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */
+#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
+#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
+#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
+#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
+#define NT_ARM_VFP 0x400 /* ARM VFP registers */
+
+/* GNU note types. */
+#define NT_GNU_ABI_TAG 1
+#define NT_GNU_HWCAP 2
+#define NT_GNU_BUILD_ID 3
+#define NT_GNU_GOLD_VERSION 4
+#define NT_GNU_PROPERTY_TYPE_0 5
+
+#define GNU_PROPERTY_LOPROC 0xc0000000
+#define GNU_PROPERTY_HIPROC 0xdfffffff
+
+#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002
+
+#define GNU_PROPERTY_X86_FEATURE_1_IBT 0x00000001
+#define GNU_PROPERTY_X86_FEATURE_1_SHSTK 0x00000002
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_LOOS 10 /* Start of operating system reserved range. */
+#define STB_GNU_UNIQUE 10 /* Unique symbol (GNU) */
+#define STB_HIOS 12 /* End of operating system reserved range. */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific semantics. */
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* Unspecified type. */
+#define STT_OBJECT 1 /* Data object. */
+#define STT_FUNC 2 /* Function. */
+#define STT_SECTION 3 /* Section. */
+#define STT_FILE 4 /* Source file. */
+#define STT_COMMON 5 /* Uninitialized common block. */
+#define STT_TLS 6 /* TLS object. */
+#define STT_NUM 7
+#define STT_LOOS 10 /* Reserved range for operating system */
+#define STT_GNU_IFUNC 10
+#define STT_HIOS 12 /* specific semantics. */
+#define STT_LOPROC 13 /* Start of processor reserved range. */
+#define STT_SPARC_REGISTER 13 /* SPARC register information. */
+#define STT_HIPROC 15 /* End of processor reserved range. */
+
+/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
+#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
+#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
+#define STV_HIDDEN 0x2 /* Not visible. */
+#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
+#define STV_EXPORTED 0x4
+#define STV_SINGLETON 0x5
+#define STV_ELIMINATE 0x6
+
+/* Special symbol table indexes. */
+#define STN_UNDEF 0 /* Undefined symbol index. */
+
+/* Symbol versioning flags. */
+#define VER_DEF_CURRENT 1
+#define VER_DEF_IDX(x) VER_NDX(x)
+
+#define VER_FLG_BASE 0x01
+#define VER_FLG_WEAK 0x02
+
+#define VER_NEED_CURRENT 1
+#define VER_NEED_WEAK (1u << 15)
+#define VER_NEED_HIDDEN VER_NDX_HIDDEN
+#define VER_NEED_IDX(x) VER_NDX(x)
+
+#define VER_NDX_LOCAL 0
+#define VER_NDX_GLOBAL 1
+#define VER_NDX_GIVEN 2
+
+#define VER_NDX_HIDDEN (1u << 15)
+#define VER_NDX(x) ((x) & ~(1u << 15))
+
+#define CA_SUNW_NULL 0
+#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */
+#define CA_SUNW_SF_1 2 /* first software capabilities entry */
+
+/*
+ * Syminfo flag values
+ */
+#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */
+ /* to object containing defn. */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */
+#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */
+ /* lazily-loaded */
+#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */
+ /* object containing defn. */
+#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */
+ /* directly bind to this symbol */
+#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */
+#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */
+
+/*
+ * Syminfo.si_boundto values.
+ */
+#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */
+#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */
+#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */
+
+/*
+ * Syminfo version values.
+ */
+#define SYMINFO_NONE 0 /* Syminfo version */
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+/* Values for ch_type (compressed section headers). */
+#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE */
+#define ELFCOMPRESS_LOOS 0x60000000 /* OS-specific */
+#define ELFCOMPRESS_HIOS 0x6fffffff
+#define ELFCOMPRESS_LOPROC 0x70000000 /* Processor-specific */
+#define ELFCOMPRESS_HIPROC 0x7fffffff
+
+/* Values for a_type. */
+#define AT_NULL 0 /* Terminates the vector. */
+#define AT_IGNORE 1 /* Ignored entry. */
+#define AT_EXECFD 2 /* File descriptor of program to load. */
+#define AT_PHDR 3 /* Program header of program already loaded. */
+#define AT_PHENT 4 /* Size of each program header entry. */
+#define AT_PHNUM 5 /* Number of program header entries. */
+#define AT_PAGESZ 6 /* Page size in bytes. */
+#define AT_BASE 7 /* Interpreter's base address. */
+#define AT_FLAGS 8 /* Flags. */
+#define AT_ENTRY 9 /* Where interpreter should transfer control. */
+#define AT_NOTELF 10 /* Program is not ELF ?? */
+#define AT_UID 11 /* Real uid. */
+#define AT_EUID 12 /* Effective uid. */
+#define AT_GID 13 /* Real gid. */
+#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
+#define AT_CANARY 16 /* Canary for SSP. */
+#define AT_CANARYLEN 17 /* Length of the canary. */
+#define AT_OSRELDATE 18 /* OSRELDATE. */
+#define AT_NCPUS 19 /* Number of CPUs. */
+#define AT_PAGESIZES 20 /* Pagesizes. */
+#define AT_PAGESIZESLEN 21 /* Number of pagesizes. */
+#define AT_TIMEKEEP 22 /* Pointer to timehands. */
+#define AT_STACKPROT 23 /* Initial stack protection. */
+#define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */
+#define AT_HWCAP 25 /* CPU feature flags. */
+#define AT_HWCAP2 26 /* CPU feature flags 2. */
+#define AT_BSDFLAGS 27 /* ELF BSD Flags. */
+#define AT_ARGC 28 /* Argument count */
+#define AT_ARGV 29 /* Argument vector */
+#define AT_ENVC 30 /* Environment count */
+#define AT_ENVV 31 /* Environment vector */
+#define AT_PS_STRINGS 32 /* struct ps_strings */
+#define AT_FXRNG 33 /* Pointer to root RNG seed version. */
+
+#define AT_COUNT 34 /* Count of defined aux entry types. */
+
+/*
+ * Relocation types.
+ *
+ * All machine architectures are defined here to allow tools on one to
+ * handle others.
+ */
+
+#define R_386_NONE 0 /* No relocation. */
+#define R_386_32 1 /* Add symbol value. */
+#define R_386_PC32 2 /* Add PC-relative symbol value. */
+#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
+#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
+#define R_386_COPY 5 /* Copy data from shared object. */
+#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_386_RELATIVE 8 /* Add load address of shared object. */
+#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
+#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
+#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
+#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
+#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
+#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
+#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
+#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
+#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
+#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
+#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
+#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
+#define R_386_SIZE32 38
+#define R_386_TLS_GOTDESC 39
+#define R_386_TLS_DESC_CALL 40
+#define R_386_TLS_DESC 41
+#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */
+#define R_386_GOT32X 43
+
+#define R_AARCH64_NONE 0 /* No relocation */
+#define R_AARCH64_ABS64 257 /* Absolute offset */
+#define R_AARCH64_ABS32 258 /* Absolute, 32-bit overflow check */
+#define R_AARCH64_ABS16 259 /* Absolute, 16-bit overflow check */
+#define R_AARCH64_PREL64 260 /* PC relative */
+#define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */
+#define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */
+#define R_AARCH64_TSTBR14 279 /* TBZ/TBNZ immediate */
+#define R_AARCH64_CONDBR19 280 /* Conditional branch immediate */
+#define R_AARCH64_JUMP26 282 /* Branch immediate */
+#define R_AARCH64_CALL26 283 /* Call immediate */
+#define R_AARCH64_COPY 1024 /* Copy data from shared object */
+#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */
+#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */
+#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */
+#define R_AARCH64_TLS_DTPREL64 1028
+#define R_AARCH64_TLS_DTPMOD64 1029
+#define R_AARCH64_TLS_TPREL64 1030
+#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */
+#define R_AARCH64_IRELATIVE 1032
+
+#define R_ARM_NONE 0 /* No relocation. */
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_REL32 3
+#define R_ARM_PC13 4
+#define R_ARM_ABS16 5
+#define R_ARM_ABS12 6
+#define R_ARM_THM_ABS5 7
+#define R_ARM_ABS8 8
+#define R_ARM_SBREL32 9
+#define R_ARM_THM_PC22 10
+#define R_ARM_THM_PC8 11
+#define R_ARM_AMP_VCALL9 12
+#define R_ARM_SWI24 13
+#define R_ARM_THM_SWI8 14
+#define R_ARM_XPC25 15
+#define R_ARM_THM_XPC22 16
+/* TLS relocations */
+#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
+#define R_ARM_COPY 20 /* Copy data from shared object. */
+#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */
+#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */
+#define R_ARM_RELATIVE 23 /* Add load address of shared object. */
+#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */
+#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */
+#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */
+#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */
+#define R_ARM_GNU_VTENTRY 100
+#define R_ARM_GNU_VTINHERIT 101
+#define R_ARM_RSBREL32 250
+#define R_ARM_THM_RPC22 251
+#define R_ARM_RREL32 252
+#define R_ARM_RABS32 253
+#define R_ARM_RPC24 254
+#define R_ARM_RBASE 255
+
+/* Name Value Field Calculation */
+#define R_IA_64_NONE 0 /* None */
+#define R_IA_64_IMM14 0x21 /* immediate14 S + A */
+#define R_IA_64_IMM22 0x22 /* immediate22 S + A */
+#define R_IA_64_IMM64 0x23 /* immediate64 S + A */
+#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */
+#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */
+#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */
+#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */
+#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */
+#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */
+#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */
+#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */
+#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */
+#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */
+#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */
+#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */
+#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */
+#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */
+#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */
+#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */
+#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */
+#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */
+#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */
+#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */
+#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */
+#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */
+#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */
+#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */
+#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */
+#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */
+#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */
+#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */
+#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */
+#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */
+#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */
+#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */
+#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */
+#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */
+#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */
+#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */
+#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */
+#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */
+#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */
+#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */
+#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */
+#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */
+#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */
+#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */
+#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */
+#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */
+#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */
+#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */
+#define R_IA_64_SUB 0x85 /* immediate64 A - S */
+#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */
+#define R_IA_64_LDXMOV 0x87 /* immediate22 special */
+#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */
+#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */
+#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */
+#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */
+#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */
+#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */
+#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */
+#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */
+#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */
+#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */
+#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */
+#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */
+#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */
+#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */
+#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */
+
+#define R_MIPS_NONE 0 /* No reloc */
+#define R_MIPS_16 1 /* Direct 16 bit */
+#define R_MIPS_32 2 /* Direct 32 bit */
+#define R_MIPS_REL32 3 /* PC relative 32 bit */
+#define R_MIPS_26 4 /* Direct 26 bit shifted */
+#define R_MIPS_HI16 5 /* High 16 bit */
+#define R_MIPS_LO16 6 /* Low 16 bit */
+#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
+#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
+#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
+#define R_MIPS_PC16 10 /* PC relative 16 bit */
+#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
+#define R_MIPS_64 18 /* Direct 64 bit */
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */
+#define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */
+#define R_MIPS_SUB 24
+#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
+#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
+#define R_MIPS_JALR 37
+#define R_MIPS_TLS_GD 42
+#define R_MIPS_COPY 126
+#define R_MIPS_JUMP_SLOT 127
+
+#define R_PPC_NONE 0 /* No relocation. */
+#define R_PPC_ADDR32 1
+#define R_PPC_ADDR24 2
+#define R_PPC_ADDR16 3
+#define R_PPC_ADDR16_LO 4
+#define R_PPC_ADDR16_HI 5
+#define R_PPC_ADDR16_HA 6
+#define R_PPC_ADDR14 7
+#define R_PPC_ADDR14_BRTAKEN 8
+#define R_PPC_ADDR14_BRNTAKEN 9
+#define R_PPC_REL24 10
+#define R_PPC_REL14 11
+#define R_PPC_REL14_BRTAKEN 12
+#define R_PPC_REL14_BRNTAKEN 13
+#define R_PPC_GOT16 14
+#define R_PPC_GOT16_LO 15
+#define R_PPC_GOT16_HI 16
+#define R_PPC_GOT16_HA 17
+#define R_PPC_PLTREL24 18
+#define R_PPC_COPY 19
+#define R_PPC_GLOB_DAT 20
+#define R_PPC_JMP_SLOT 21
+#define R_PPC_RELATIVE 22
+#define R_PPC_LOCAL24PC 23
+#define R_PPC_UADDR32 24
+#define R_PPC_UADDR16 25
+#define R_PPC_REL32 26
+#define R_PPC_PLT32 27
+#define R_PPC_PLTREL32 28
+#define R_PPC_PLT16_LO 29
+#define R_PPC_PLT16_HI 30
+#define R_PPC_PLT16_HA 31
+#define R_PPC_SDAREL16 32
+#define R_PPC_SECTOFF 33
+#define R_PPC_SECTOFF_LO 34
+#define R_PPC_SECTOFF_HI 35
+#define R_PPC_SECTOFF_HA 36
+#define R_PPC_IRELATIVE 248
+
+/*
+ * 64-bit relocations
+ */
+#define R_PPC64_ADDR64 38
+#define R_PPC64_ADDR16_HIGHER 39
+#define R_PPC64_ADDR16_HIGHERA 40
+#define R_PPC64_ADDR16_HIGHEST 41
+#define R_PPC64_ADDR16_HIGHESTA 42
+#define R_PPC64_UADDR64 43
+#define R_PPC64_REL64 44
+#define R_PPC64_PLT64 45
+#define R_PPC64_PLTREL64 46
+#define R_PPC64_TOC16 47
+#define R_PPC64_TOC16_LO 48
+#define R_PPC64_TOC16_HI 49
+#define R_PPC64_TOC16_HA 50
+#define R_PPC64_TOC 51
+#define R_PPC64_DTPMOD64 68
+#define R_PPC64_TPREL64 73
+#define R_PPC64_DTPREL64 78
+
+/*
+ * TLS relocations
+ */
+#define R_PPC_TLS 67
+#define R_PPC_DTPMOD32 68
+#define R_PPC_TPREL16 69
+#define R_PPC_TPREL16_LO 70
+#define R_PPC_TPREL16_HI 71
+#define R_PPC_TPREL16_HA 72
+#define R_PPC_TPREL32 73
+#define R_PPC_DTPREL16 74
+#define R_PPC_DTPREL16_LO 75
+#define R_PPC_DTPREL16_HI 76
+#define R_PPC_DTPREL16_HA 77
+#define R_PPC_DTPREL32 78
+#define R_PPC_GOT_TLSGD16 79
+#define R_PPC_GOT_TLSGD16_LO 80
+#define R_PPC_GOT_TLSGD16_HI 81
+#define R_PPC_GOT_TLSGD16_HA 82
+#define R_PPC_GOT_TLSLD16 83
+#define R_PPC_GOT_TLSLD16_LO 84
+#define R_PPC_GOT_TLSLD16_HI 85
+#define R_PPC_GOT_TLSLD16_HA 86
+#define R_PPC_GOT_TPREL16 87
+#define R_PPC_GOT_TPREL16_LO 88
+#define R_PPC_GOT_TPREL16_HI 89
+#define R_PPC_GOT_TPREL16_HA 90
+
+/*
+ * The remaining relocs are from the Embedded ELF ABI, and are not in the
+ * SVR4 ELF ABI.
+ */
+
+#define R_PPC_EMB_NADDR32 101
+#define R_PPC_EMB_NADDR16 102
+#define R_PPC_EMB_NADDR16_LO 103
+#define R_PPC_EMB_NADDR16_HI 104
+#define R_PPC_EMB_NADDR16_HA 105
+#define R_PPC_EMB_SDAI16 106
+#define R_PPC_EMB_SDA2I16 107
+#define R_PPC_EMB_SDA2REL 108
+#define R_PPC_EMB_SDA21 109
+#define R_PPC_EMB_MRKREF 110
+#define R_PPC_EMB_RELSEC16 111
+#define R_PPC_EMB_RELST_LO 112
+#define R_PPC_EMB_RELST_HI 113
+#define R_PPC_EMB_RELST_HA 114
+#define R_PPC_EMB_BIT_FLD 115
+#define R_PPC_EMB_RELSDA 116
+
+/*
+ * RISC-V relocation types.
+ */
+
+/* Relocation types used by the dynamic linker. */
+#define R_RISCV_NONE 0
+#define R_RISCV_32 1
+#define R_RISCV_64 2
+#define R_RISCV_RELATIVE 3
+#define R_RISCV_COPY 4
+#define R_RISCV_JUMP_SLOT 5
+#define R_RISCV_TLS_DTPMOD32 6
+#define R_RISCV_TLS_DTPMOD64 7
+#define R_RISCV_TLS_DTPREL32 8
+#define R_RISCV_TLS_DTPREL64 9
+#define R_RISCV_TLS_TPREL32 10
+#define R_RISCV_TLS_TPREL64 11
+
+/* Relocation types not used by the dynamic linker. */
+#define R_RISCV_BRANCH 16
+#define R_RISCV_JAL 17
+#define R_RISCV_CALL 18
+#define R_RISCV_CALL_PLT 19
+#define R_RISCV_GOT_HI20 20
+#define R_RISCV_TLS_GOT_HI20 21
+#define R_RISCV_TLS_GD_HI20 22
+#define R_RISCV_PCREL_HI20 23
+#define R_RISCV_PCREL_LO12_I 24
+#define R_RISCV_PCREL_LO12_S 25
+#define R_RISCV_HI20 26
+#define R_RISCV_LO12_I 27
+#define R_RISCV_LO12_S 28
+#define R_RISCV_TPREL_HI20 29
+#define R_RISCV_TPREL_LO12_I 30
+#define R_RISCV_TPREL_LO12_S 31
+#define R_RISCV_TPREL_ADD 32
+#define R_RISCV_ADD8 33
+#define R_RISCV_ADD16 34
+#define R_RISCV_ADD32 35
+#define R_RISCV_ADD64 36
+#define R_RISCV_SUB8 37
+#define R_RISCV_SUB16 38
+#define R_RISCV_SUB32 39
+#define R_RISCV_SUB64 40
+#define R_RISCV_GNU_VTINHERIT 41
+#define R_RISCV_GNU_VTENTRY 42
+#define R_RISCV_ALIGN 43
+#define R_RISCV_RVC_BRANCH 44
+#define R_RISCV_RVC_JUMP 45
+#define R_RISCV_RVC_LUI 46
+#define R_RISCV_GPREL_I 47
+#define R_RISCV_GPREL_S 48
+#define R_RISCV_TPREL_I 49
+#define R_RISCV_TPREL_S 50
+#define R_RISCV_RELAX 51
+#define R_RISCV_SUB6 52
+#define R_RISCV_SET6 53
+#define R_RISCV_SET8 54
+#define R_RISCV_SET16 55
+#define R_RISCV_SET32 56
+#define R_RISCV_32_PCREL 57
+#define R_RISCV_IRELATIVE 58
+
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
+#define R_SPARC_PC_HH22 37
+#define R_SPARC_PC_HM10 38
+#define R_SPARC_PC_LM22 39
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_GLOB_JMP 42
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+#define R_SPARC_DISP64 46
+#define R_SPARC_PLT64 47
+#define R_SPARC_HIX22 48
+#define R_SPARC_LOX10 49
+#define R_SPARC_H44 50
+#define R_SPARC_M44 51
+#define R_SPARC_L44 52
+#define R_SPARC_REGISTER 53
+#define R_SPARC_UA64 54
+#define R_SPARC_UA16 55
+#define R_SPARC_TLS_GD_HI22 56
+#define R_SPARC_TLS_GD_LO10 57
+#define R_SPARC_TLS_GD_ADD 58
+#define R_SPARC_TLS_GD_CALL 59
+#define R_SPARC_TLS_LDM_HI22 60
+#define R_SPARC_TLS_LDM_LO10 61
+#define R_SPARC_TLS_LDM_ADD 62
+#define R_SPARC_TLS_LDM_CALL 63
+#define R_SPARC_TLS_LDO_HIX22 64
+#define R_SPARC_TLS_LDO_LOX10 65
+#define R_SPARC_TLS_LDO_ADD 66
+#define R_SPARC_TLS_IE_HI22 67
+#define R_SPARC_TLS_IE_LO10 68
+#define R_SPARC_TLS_IE_LD 69
+#define R_SPARC_TLS_IE_LDX 70
+#define R_SPARC_TLS_IE_ADD 71
+#define R_SPARC_TLS_LE_HIX22 72
+#define R_SPARC_TLS_LE_LOX10 73
+#define R_SPARC_TLS_DTPMOD32 74
+#define R_SPARC_TLS_DTPMOD64 75
+#define R_SPARC_TLS_DTPOFF32 76
+#define R_SPARC_TLS_DTPOFF64 77
+#define R_SPARC_TLS_TPOFF32 78
+#define R_SPARC_TLS_TPOFF64 79
+
+#define R_X86_64_NONE 0 /* No relocation. */
+#define R_X86_64_64 1 /* Add 64 bit symbol value. */
+#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
+#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
+#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
+#define R_X86_64_COPY 5 /* Copy data from shared object. */
+#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
+#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
+#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
+#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
+#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
+#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
+#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
+#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
+#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
+#define R_X86_64_PC64 24 /* PC-relative 64 bit signed sym value. */
+#define R_X86_64_GOTOFF64 25
+#define R_X86_64_GOTPC32 26
+#define R_X86_64_GOT64 27
+#define R_X86_64_GOTPCREL64 28
+#define R_X86_64_GOTPC64 29
+#define R_X86_64_GOTPLT64 30
+#define R_X86_64_PLTOFF64 31
+#define R_X86_64_SIZE32 32
+#define R_X86_64_SIZE64 33
+#define R_X86_64_GOTPC32_TLSDESC 34
+#define R_X86_64_TLSDESC_CALL 35
+#define R_X86_64_TLSDESC 36
+#define R_X86_64_IRELATIVE 37
+#define R_X86_64_RELATIVE64 38
+/* 39 and 40 were BND-related, already decomissioned */
+#define R_X86_64_GOTPCRELX 41
+#define R_X86_64_REX_GOTPCRELX 42
+
+#define ELF_BSDF_SIGFASTBLK 0x0001 /* Kernel supports fast sigblock */
+
+#endif /* !_SYS_ELF_COMMON_H_ */
diff --git a/Utilities/cmjsoncpp/include/json/allocator.h b/Utilities/cmjsoncpp/include/json/allocator.h
index 9562436c6..a685da124 100644
--- a/Utilities/cmjsoncpp/include/json/allocator.h
+++ b/Utilities/cmjsoncpp/include/json/allocator.h
@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
-#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
@@ -14,89 +14,80 @@
#endif
namespace Json {
-template<typename T>
-class SecureAllocator {
- public:
- // Type definitions
- using value_type = T;
- using pointer = T*;
- using const_pointer = const T*;
- using reference = T&;
- using const_reference = const T&;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
-
- /**
- * Allocate memory for N items using the standard allocator.
- */
- pointer allocate(size_type n) {
- // allocate using "global operator new"
- return static_cast<pointer>(::operator new(n * sizeof(T)));
- }
-
- /**
- * Release memory which was allocated for N items at pointer P.
- *
- * The memory block is filled with zeroes before being released.
- * The pointer argument is tagged as "volatile" to prevent the
- * compiler optimizing out this critical step.
- */
- void deallocate(volatile pointer p, size_type n) {
- std::memset(p, 0, n * sizeof(T));
- // free using "global operator delete"
- ::operator delete(p);
- }
-
- /**
- * Construct an item in-place at pointer P.
- */
- template<typename... Args>
- void construct(pointer p, Args&&... args) {
- // construct using "placement new" and "perfect forwarding"
- ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
- }
-
- size_type max_size() const {
- return size_t(-1) / sizeof(T);
- }
-
- pointer address( reference x ) const {
- return std::addressof(x);
- }
-
- const_pointer address( const_reference x ) const {
- return std::addressof(x);
- }
-
- /**
- * Destroy an item in-place at pointer P.
- */
- void destroy(pointer p) {
- // destroy using "explicit destructor"
- p->~T();
- }
-
- // Boilerplate
- SecureAllocator() {}
- template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
- template<typename U> struct rebind { using other = SecureAllocator<U>; };
+template <typename T> class SecureAllocator {
+public:
+ // Type definitions
+ using value_type = T;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ /**
+ * Allocate memory for N items using the standard allocator.
+ */
+ pointer allocate(size_type n) {
+ // allocate using "global operator new"
+ return static_cast<pointer>(::operator new(n * sizeof(T)));
+ }
+
+ /**
+ * Release memory which was allocated for N items at pointer P.
+ *
+ * The memory block is filled with zeroes before being released.
+ * The pointer argument is tagged as "volatile" to prevent the
+ * compiler optimizing out this critical step.
+ */
+ void deallocate(volatile pointer p, size_type n) {
+ std::memset(p, 0, n * sizeof(T));
+ // free using "global operator delete"
+ ::operator delete(p);
+ }
+
+ /**
+ * Construct an item in-place at pointer P.
+ */
+ template <typename... Args> void construct(pointer p, Args&&... args) {
+ // construct using "placement new" and "perfect forwarding"
+ ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+ }
+
+ size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+ pointer address(reference x) const { return std::addressof(x); }
+
+ const_pointer address(const_reference x) const { return std::addressof(x); }
+
+ /**
+ * Destroy an item in-place at pointer P.
+ */
+ void destroy(pointer p) {
+ // destroy using "explicit destructor"
+ p->~T();
+ }
+
+ // Boilerplate
+ SecureAllocator() {}
+ template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
+ template <typename U> struct rebind { using other = SecureAllocator<U>; };
};
-
-template<typename T, typename U>
+template <typename T, typename U>
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
- return true;
+ return true;
}
-template<typename T, typename U>
+template <typename T, typename U>
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
- return false;
+ return false;
}
-} //namespace Json
+} // namespace Json
#if !defined(__SUNPRO_CC)
#pragma pack(pop)
#endif
-#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
+#endif // JSON_ALLOCATOR_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/assertions.h b/Utilities/cmjsoncpp/include/json/assertions.h
index f64913fbe..415c46309 100644
--- a/Utilities/cmjsoncpp/include/json/assertions.h
+++ b/Utilities/cmjsoncpp/include/json/assertions.h
@@ -3,14 +3,14 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
-#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#ifndef JSON_ASSERTIONS_H_INCLUDED
+#define JSON_ASSERTIONS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <stdlib.h>
+#include <cstdlib>
#include <sstream>
/** It should not be possible for a maliciously designed file to
@@ -20,35 +20,42 @@
#if JSON_USE_EXCEPTION
// @todo <= add detail about condition in exception
-# define JSON_ASSERT(condition) \
- {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
-
-# define JSON_FAIL_MESSAGE(message) \
- { \
- JSONCPP_OSTRINGSTREAM oss; oss << message; \
+#define JSON_ASSERT(condition) \
+ do { \
+ if (!(condition)) { \
+ Json::throwLogicError("assert json failed"); \
+ } \
+ } while (0)
+
+#define JSON_FAIL_MESSAGE(message) \
+ do { \
+ OStringStream oss; \
+ oss << message; \
Json::throwLogicError(oss.str()); \
abort(); \
- }
+ } while (0)
#else // JSON_USE_EXCEPTION
-# define JSON_ASSERT(condition) assert(condition)
+#define JSON_ASSERT(condition) assert(condition)
// The call to assert() will show the failure message in debug builds. In
// release builds we abort, for a core-dump or debugger.
-# define JSON_FAIL_MESSAGE(message) \
+#define JSON_FAIL_MESSAGE(message) \
{ \
- JSONCPP_OSTRINGSTREAM oss; oss << message; \
+ OStringStream oss; \
+ oss << message; \
assert(false && oss.str().c_str()); \
abort(); \
}
-
#endif
#define JSON_ASSERT_MESSAGE(condition, message) \
- if (!(condition)) { \
- JSON_FAIL_MESSAGE(message); \
- }
+ do { \
+ if (!(condition)) { \
+ JSON_FAIL_MESSAGE(message); \
+ } \
+ } while (0)
-#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#endif // JSON_ASSERTIONS_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/config.h b/Utilities/cmjsoncpp/include/json/config.h
index 2cc8462b3..f03b7469a 100644
--- a/Utilities/cmjsoncpp/include/json/config.h
+++ b/Utilities/cmjsoncpp/include/json/config.h
@@ -6,26 +6,18 @@
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
-// Include KWSys Large File Support configuration.
-#include <cmsys/Configure.h>
-
-#include <stddef.h>
-#include <string> //typedef String
-#include <stdint.h> //typedef int64_t, uint64_t
-
#if defined(_MSC_VER)
# pragma warning(push,1)
#endif
-/// If defined, indicates that json library is embedded in CppTL library.
-//# define JSON_IN_CPPTL 1
-
-/// If defined, indicates that json may leverage CppTL library
-//# define JSON_USE_CPPTL 1
-/// If defined, indicates that cpptl vector based map should be used instead of
-/// std::map
-/// as Value container.
-//# define JSON_USE_CPPTL_SMALLMAP 1
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
@@ -33,108 +25,73 @@
#define JSON_USE_EXCEPTION 1
#endif
-/// If defined, indicates that the source file is amalgated
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
-/// Remarks: it is automatically defined in the generated amalgated header.
+/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
-#ifdef JSON_IN_CPPTL
-#include <cpptl/config.h>
-#ifndef JSON_USE_CPPTL
-#define JSON_USE_CPPTL 1
-#endif
-#endif
-
-#ifdef JSON_IN_CPPTL
-#define JSON_API CPPTL_API
-#elif defined(JSON_DLL_BUILD)
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)
+
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
-#endif // ifdef JSON_IN_CPPTL
+#endif // ifdef JSON_DLL_BUILD
+
#if !defined(JSON_API)
#define JSON_API
#endif
-// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
-// integer
-// Storages, and 64 bits integer support is disabled.
-// #define JSON_NO_INT64 1
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error \
+ "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
+#endif
-#if defined(_MSC_VER) // MSVC
-# if _MSC_VER <= 1200 // MSVC 6
- // Microsoft Visual Studio 6 only support conversion from __int64 to double
- // (no conversion from unsigned __int64).
-# define JSON_USE_INT64_DOUBLE_CONVERSION 1
- // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
- // characters in the debug information)
- // All projects I've ever seen with VS6 were using this globally (not bothering
- // with pragma push/pop).
-# pragma warning(disable : 4786)
-# endif // MSVC 6
-
-#endif // defined(_MSC_VER)
-
-// In c++11 the override keyword allows you to explicity define that a function
-// is intended to override the base-class version. This makes the code more
-// managable and fixes a set of common hard-to-find bugs.
-#if __cplusplus >= 201103L
-# define JSONCPP_OVERRIDE override
-# define JSONCPP_NOEXCEPT noexcept
-#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
-# define JSONCPP_OVERRIDE override
-# define JSONCPP_NOEXCEPT throw()
-#elif defined(_MSC_VER) && _MSC_VER >= 1900
-# define JSONCPP_OVERRIDE override
-# define JSONCPP_NOEXCEPT noexcept
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+ const char* format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else
-# define JSONCPP_OVERRIDE
-# define JSONCPP_NOEXCEPT throw()
+#define jsoncpp_snprintf std::snprintf
#endif
-#ifndef JSON_HAS_RVALUE_REFERENCES
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
-#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // MSVC >= 2010
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
#ifdef __clang__
-#if __has_feature(cxx_rvalue_references)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // has_feature
-
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // GXX_EXPERIMENTAL
-
-#endif // __clang__ || __GNUC__
-
-#endif // not defined JSON_HAS_RVALUE_REFERENCES
-
-#ifndef JSON_HAS_RVALUE_REFERENCES
-#define JSON_HAS_RVALUE_REFERENCES 0
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif
-
-#ifdef __clang__
-# if __has_extension(attribute_deprecated_with_message)
-# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
-# endif
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
-# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
-# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
-# endif // GNUC version
-#elif defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
- /// Indicates that the following function is deprecated.
-# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+#endif // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+ // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif // __clang__ || __GNUC__ || _MSC_VER
#undef JSONCPP_DEPRECATED // no deprecations in CMake copy
@@ -142,53 +99,58 @@
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
-#if __GNUC__ >= 6
-# define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif
#if !defined(JSON_IS_AMALGAMATION)
-# include "version.h"
-
-# if JSONCPP_USING_SECURE_MEMORY
-# include "allocator.h" //typedef Allocator
-# endif
+#include "allocator.h"
+#include "version.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
-typedef int Int;
-typedef unsigned int UInt;
+using Int = int;
+using UInt = unsigned int;
#if defined(JSON_NO_INT64)
-typedef int LargestInt;
-typedef unsigned int LargestUInt;
+using LargestInt = int;
+using LargestUInt = unsigned int;
#undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long
-typedef int64_t Int64;
-typedef uint64_t UInt64;
-#endif // if defined(_MSC_VER)
-typedef Int64 LargestInt;
-typedef UInt64 LargestUInt;
+using Int64 = int64_t;
+using UInt64 = uint64_t;
+#endif // if defined(_MSC_VER)
+using LargestInt = Int64;
+using LargestUInt = UInt64;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
-#if JSONCPP_USING_SECURE_MEMORY
-#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
-#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
-#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
-#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
-#define JSONCPP_ISTREAM std::istream
-#else
-#define JSONCPP_STRING std::string
-#define JSONCPP_OSTRINGSTREAM std::ostringstream
-#define JSONCPP_OSTREAM std::ostream
-#define JSONCPP_ISTRINGSTREAM std::istringstream
-#define JSONCPP_ISTREAM std::istream
-#endif // if JSONCPP_USING_SECURE_MEMORY
-} // end namespace Json
+
+template <typename T>
+using Allocator =
+ typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+ std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+ std::basic_istringstream<String::value_type, String::traits_type,
+ String::allocator_type>;
+using OStringStream =
+ std::basic_ostringstream<String::value_type, String::traits_type,
+ String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
#endif // JSON_CONFIG_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/forwards.h b/Utilities/cmjsoncpp/include/json/forwards.h
index 70bbe191c..affe33a7f 100644
--- a/Utilities/cmjsoncpp/include/json/forwards.h
+++ b/Utilities/cmjsoncpp/include/json/forwards.h
@@ -13,17 +13,23 @@
namespace Json {
// writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
class FastWriter;
class StyledWriter;
+class StyledStreamWriter;
// reader.h
class Reader;
+class CharReader;
+class CharReaderBuilder;
-// features.h
+// json_features.h
class Features;
// value.h
-typedef unsigned int ArrayIndex;
+using ArrayIndex = unsigned int;
class StaticString;
class Path;
class PathArgument;
diff --git a/Utilities/cmjsoncpp/include/json/json.h b/Utilities/cmjsoncpp/include/json/json.h
index 59646723b..5c776a160 100644
--- a/Utilities/cmjsoncpp/include/json/json.h
+++ b/Utilities/cmjsoncpp/include/json/json.h
@@ -6,9 +6,10 @@
#ifndef JSON_JSON_H_INCLUDED
#define JSON_JSON_H_INCLUDED
-#include "value.h"
+#include "config.h"
+#include "json_features.h"
#include "reader.h"
+#include "value.h"
#include "writer.h"
-#include "features.h"
#endif // JSON_JSON_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/features.h b/Utilities/cmjsoncpp/include/json/json_features.h
index 365abb356..6b99b4d75 100644
--- a/Utilities/cmjsoncpp/include/json/features.h
+++ b/Utilities/cmjsoncpp/include/json/json_features.h
@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
-#define CPPTL_JSON_FEATURES_H_INCLUDED
+#ifndef JSON_FEATURES_H_INCLUDED
+#define JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
@@ -43,17 +43,17 @@ public:
Features();
/// \c true if comments are allowed. Default: \c true.
- bool allowComments_;
+ bool allowComments_{true};
/// \c true if root must be either an array or an object value. Default: \c
/// false.
- bool strictRoot_;
+ bool strictRoot_{false};
/// \c true if dropped null placeholders are allowed. Default: \c false.
- bool allowDroppedNullPlaceholders_;
+ bool allowDroppedNullPlaceholders_{false};
/// \c true if numeric object key are allowed. Default: \c false.
- bool allowNumericKeys_;
+ bool allowNumericKeys_{false};
};
} // namespace Json
@@ -62,4 +62,4 @@ public:
#pragma pack(pop)
#endif
-#endif // CPPTL_JSON_FEATURES_H_INCLUDED
+#endif // JSON_FEATURES_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/reader.h b/Utilities/cmjsoncpp/include/json/reader.h
index 667246a0b..7ad0be6c9 100644
--- a/Utilities/cmjsoncpp/include/json/reader.h
+++ b/Utilities/cmjsoncpp/include/json/reader.h
@@ -3,18 +3,18 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-#ifndef CPPTL_JSON_READER_H_INCLUDED
-#define CPPTL_JSON_READER_H_INCLUDED
+#ifndef JSON_READER_H_INCLUDED
+#define JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
-#include "features.h"
+#include "json_features.h"
#include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <deque>
#include <iosfwd>
+#include <istream>
#include <stack>
#include <string>
-#include <istream>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
@@ -30,132 +30,130 @@
namespace Json {
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
- *Value.
+ * Value.
*
* deprecated Use CharReader and CharReaderBuilder.
*/
-class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
+
+class JSONCPP_DEPRECATED(
+ "Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
public:
- typedef char Char;
- typedef const Char* Location;
+ using Char = char;
+ using Location = const Char*;
/** \brief An error tagged with where in the JSON text it was encountered.
*
* The offsets give the [start, limit) range of bytes within the text. Note
* that this is bytes, not codepoints.
- *
*/
struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
- JSONCPP_STRING message;
+ String message;
};
- /** \brief Constructs a Reader allowing all features
- * for parsing.
+ /** \brief Constructs a Reader allowing all features for parsing.
*/
+ JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader();
- /** \brief Constructs a Reader allowing the specified feature set
- * for parsing.
+ /** \brief Constructs a Reader allowing the specified feature set for parsing.
*/
+ JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
Reader(const Features& features);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
* document.
- * \param document UTF-8 encoded string containing the document to read.
- * \param root [out] Contains the root value of the document if it was
- * successfully parsed.
- * \param collectComments \c true to collect comment and allow writing them
- * back during
- * serialization, \c false to discard comments.
- * This parameter is ignored if
- * Features::allowComments_
- * is \c false.
+ *
+ * \param document UTF-8 encoded string containing the document
+ * to read.
+ * \param[out] root Contains the root value of the document if it
+ * was successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing
+ * them back during serialization, \c false to
+ * discard comments. This parameter is ignored
+ * if Features::allowComments_ is \c false.
* \return \c true if the document was successfully parsed, \c false if an
* error occurred.
*/
- bool
- parse(const std::string& document, Value& root, bool collectComments = true);
+ bool parse(const std::string& document, Value& root,
+ bool collectComments = true);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
- document.
- * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
- document to read.
- * \param endDoc Pointer on the end of the UTF-8 encoded string of the
- document to read.
- * Must be >= beginDoc.
- * \param root [out] Contains the root value of the document if it was
- * successfully parsed.
- * \param collectComments \c true to collect comment and allow writing them
- back during
- * serialization, \c false to discard comments.
- * This parameter is ignored if
- Features::allowComments_
- * is \c false.
+ * document.
+ *
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded
+ * string of the document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string
+ * of the document to read. Must be >= beginDoc.
+ * \param[out] root Contains the root value of the document if it
+ * was successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing
+ * them back during serialization, \c false to
+ * discard comments. This parameter is ignored
+ * if Features::allowComments_ is \c false.
* \return \c true if the document was successfully parsed, \c false if an
- error occurred.
+ * error occurred.
*/
- bool parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
+ bool parse(const char* beginDoc, const char* endDoc, Value& root,
bool collectComments = true);
/// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&).
- bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
+ bool parse(IStream& is, Value& root, bool collectComments = true);
/** \brief Returns a user friendly string that list errors in the parsed
* document.
- * \return Formatted error message with the list of errors with their location
- * in
- * the parsed document. An empty string is returned if no error
- * occurred
- * during parsing.
+ *
+ * \return Formatted error message with the list of errors with their
+ * location in the parsed document. An empty string is returned if no error
+ * occurred during parsing.
* deprecated Use getFormattedErrorMessages() instead (typo fix).
*/
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
- JSONCPP_STRING getFormatedErrorMessages() const;
+ String getFormatedErrorMessages() const;
/** \brief Returns a user friendly string that list errors in the parsed
* document.
- * \return Formatted error message with the list of errors with their location
- * in
- * the parsed document. An empty string is returned if no error
- * occurred
- * during parsing.
+ *
+ * \return Formatted error message with the list of errors with their
+ * location in the parsed document. An empty string is returned if no error
+ * occurred during parsing.
*/
- JSONCPP_STRING getFormattedErrorMessages() const;
+ String getFormattedErrorMessages() const;
- /** \brief Returns a vector of structured erros encounted while parsing.
+ /** \brief Returns a vector of structured errors encountered while parsing.
+ *
* \return A (possibly empty) vector of StructuredError objects. Currently
- * only one error can be returned, but the caller should tolerate
- * multiple
- * errors. This can occur if the parser recovers from a non-fatal
- * parse error and then encounters additional errors.
+ * only one error can be returned, but the caller should tolerate multiple
+ * errors. This can occur if the parser recovers from a non-fatal parse
+ * error and then encounters additional errors.
*/
std::vector<StructuredError> getStructuredErrors() const;
/** \brief Add a semantic error message.
- * \param value JSON Value location associated with the error
+ *
+ * \param value JSON Value location associated with the error
* \param message The error message.
- * \return \c true if the error was successfully added, \c false if the
- * Value offset exceeds the document size.
+ * \return \c true if the error was successfully added, \c false if the Value
+ * offset exceeds the document size.
*/
- bool pushError(const Value& value, const JSONCPP_STRING& message);
+ bool pushError(const Value& value, const String& message);
/** \brief Add a semantic error message with extra context.
- * \param value JSON Value location associated with the error
+ *
+ * \param value JSON Value location associated with the error
* \param message The error message.
- * \param extra Additional JSON Value location to contextualize the error
+ * \param extra Additional JSON Value location to contextualize the error
* \return \c true if the error was successfully added, \c false if either
* Value offset exceeds the document size.
*/
- bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+ bool pushError(const Value& value, const String& message, const Value& extra);
/** \brief Return whether there are any errors.
- * \return \c true if there are no errors to report \c false if
- * errors have occurred.
+ *
+ * \return \c true if there are no errors to report \c false if errors have
+ * occurred.
*/
bool good() const;
@@ -187,15 +185,15 @@ private:
class ErrorInfo {
public:
Token token_;
- JSONCPP_STRING message_;
+ String message_;
Location extra_;
};
- typedef std::deque<ErrorInfo> Errors;
+ using Errors = std::deque<ErrorInfo>;
bool readToken(Token& token);
void skipSpaces();
- bool match(Location pattern, int patternLength);
+ bool match(const Char* pattern, int patternLength);
bool readComment();
bool readCStyleComment();
bool readCppStyleComment();
@@ -207,142 +205,138 @@ private:
bool decodeNumber(Token& token);
bool decodeNumber(Token& token, Value& decoded);
bool decodeString(Token& token);
- bool decodeString(Token& token, JSONCPP_STRING& decoded);
+ bool decodeString(Token& token, String& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
- bool decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
+ bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
unsigned int& unicode);
- bool decodeUnicodeEscapeSequence(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode);
- bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+ bool decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end, unsigned int& unicode);
+ bool addError(const String& message, Token& token, Location extra = nullptr);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
+ bool addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
Value& currentValue();
Char getNextChar();
- void
- getLocationLineAndColumn(Location location, int& line, int& column) const;
- JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+ void getLocationLineAndColumn(Location location, int& line,
+ int& column) const;
+ String getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
static bool containsNewLine(Location begin, Location end);
- static JSONCPP_STRING normalizeEOL(Location begin, Location end);
+ static String normalizeEOL(Location begin, Location end);
- typedef std::stack<Value*> Nodes;
+ using Nodes = std::stack<Value*>;
Nodes nodes_;
Errors errors_;
- JSONCPP_STRING document_;
- Location begin_;
- Location end_;
- Location current_;
- Location lastValueEnd_;
- Value* lastValue_;
- JSONCPP_STRING commentsBefore_;
+ String document_;
+ Location begin_{};
+ Location end_{};
+ Location current_{};
+ Location lastValueEnd_{};
+ Value* lastValue_{};
+ String commentsBefore_;
Features features_;
- bool collectComments_;
-}; // Reader
+ bool collectComments_{};
+}; // Reader
/** Interface for reading JSON from a char array.
*/
class JSON_API CharReader {
public:
- virtual ~CharReader() {}
+ virtual ~CharReader() = default;
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
- document.
- * The document must be a UTF-8 encoded string containing the document to read.
+ * document. The document must be a UTF-8 encoded string containing the
+ * document to read.
*
- * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
- document to read.
- * \param endDoc Pointer on the end of the UTF-8 encoded string of the
- document to read.
- * Must be >= beginDoc.
- * \param root [out] Contains the root value of the document if it was
- * successfully parsed.
- * \param errs [out] Formatted error messages (if not NULL)
- * a user friendly string that lists errors in the parsed
- * document.
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded string
+ * of the document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+ * document to read. Must be >= beginDoc.
+ * \param[out] root Contains the root value of the document if it was
+ * successfully parsed.
+ * \param[out] errs Formatted error messages (if not NULL) a user
+ * friendly string that lists errors in the parsed
+ * document.
* \return \c true if the document was successfully parsed, \c false if an
- error occurred.
+ * error occurred.
*/
- virtual bool parse(
- char const* beginDoc, char const* endDoc,
- Value* root, JSONCPP_STRING* errs) = 0;
+ virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
+ String* errs) = 0;
class JSON_API Factory {
public:
- virtual ~Factory() {}
+ virtual ~Factory() = default;
/** \brief Allocate a CharReader via operator new().
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
virtual CharReader* newCharReader() const = 0;
- }; // Factory
-}; // CharReader
+ }; // Factory
+}; // CharReader
/** \brief Build a CharReader implementation.
-
-Usage:
-\code
- using namespace Json;
- CharReaderBuilder builder;
- builder["collectComments"] = false;
- Value value;
- JSONCPP_STRING errs;
- bool ok = parseFromStream(builder, std::cin, &value, &errs);
-\endcode
-*/
+ *
+ * Usage:
+ * \code
+ * using namespace Json;
+ * CharReaderBuilder builder;
+ * builder["collectComments"] = false;
+ * Value value;
+ * String errs;
+ * bool ok = parseFromStream(builder, std::cin, &value, &errs);
+ * \endcode
+ */
class JSON_API CharReaderBuilder : public CharReader::Factory {
public:
// Note: We use a Json::Value so that we can add data-members to this class
// without a major version bump.
/** Configuration of this builder.
- These are case-sensitive.
- Available settings (case-sensitive):
- - `"collectComments": false or true`
- - true to collect comment and allow writing them
- back during serialization, false to discard comments.
- This parameter is ignored if allowComments is false.
- - `"allowComments": false or true`
- - true if comments are allowed.
- - `"strictRoot": false or true`
- - true if root must be either an array or an object value
- - `"allowDroppedNullPlaceholders": false or true`
- - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
- - `"allowNumericKeys": false or true`
- - true if numeric object keys are allowed.
- - `"allowSingleQuotes": false or true`
- - true if '' are allowed for strings (both keys and values)
- - `"stackLimit": integer`
- - Exceeding stackLimit (recursive depth of `readValue()`) will
- cause an exception.
- - This is a security issue (seg-faults caused by deeply nested JSON),
- so the default is low.
- - `"failIfExtra": false or true`
- - If true, `parse()` returns false when extra non-whitespace trails
- the JSON value in the input string.
- - `"rejectDupKeys": false or true`
- - If true, `parse()` returns false when a key is duplicated within an object.
- - `"allowSpecialFloats": false or true`
- - If true, special float values (NaNs and infinities) are allowed
- and their values are lossfree restorable.
-
- You can examine 'settings_` yourself
- to see the defaults. You can also write and read them just like any
- JSON Value.
- \sa setDefaults()
- */
+ * These are case-sensitive.
+ * Available settings (case-sensitive):
+ * - `"collectComments": false or true`
+ * - true to collect comment and allow writing them back during
+ * serialization, false to discard comments. This parameter is ignored
+ * if allowComments is false.
+ * - `"allowComments": false or true`
+ * - true if comments are allowed.
+ * - `"allowTrailingCommas": false or true`
+ * - true if trailing commas in objects and arrays are allowed.
+ * - `"strictRoot": false or true`
+ * - true if root must be either an array or an object value
+ * - `"allowDroppedNullPlaceholders": false or true`
+ * - true if dropped null placeholders are allowed. (See
+ * StreamWriterBuilder.)
+ * - `"allowNumericKeys": false or true`
+ * - true if numeric object keys are allowed.
+ * - `"allowSingleQuotes": false or true`
+ * - true if '' are allowed for strings (both keys and values)
+ * - `"stackLimit": integer`
+ * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
+ * exception.
+ * - This is a security issue (seg-faults caused by deeply nested JSON), so
+ * the default is low.
+ * - `"failIfExtra": false or true`
+ * - If true, `parse()` returns false when extra non-whitespace trails the
+ * JSON value in the input string.
+ * - `"rejectDupKeys": false or true`
+ * - If true, `parse()` returns false when a key is duplicated within an
+ * object.
+ * - `"allowSpecialFloats": false or true`
+ * - If true, special float values (NaNs and infinities) are allowed and
+ * their values are lossfree restorable.
+ *
+ * You can examine 'settings_` yourself to see the defaults. You can also
+ * write and read them just like any JSON Value.
+ * \sa setDefaults()
+ */
Json::Value settings_;
CharReaderBuilder();
- ~CharReaderBuilder() JSONCPP_OVERRIDE;
+ ~CharReaderBuilder() override;
- CharReader* newCharReader() const JSONCPP_OVERRIDE;
+ CharReader* newCharReader() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
@@ -351,7 +345,7 @@ public:
/** A simple way to update a specific setting.
*/
- Value& operator[](JSONCPP_STRING key);
+ Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
@@ -368,39 +362,37 @@ public:
};
/** Consume entire stream and use its begin/end.
- * Someday we might have a real StreamReader, but for now this
- * is convenient.
- */
-bool JSON_API parseFromStream(
- CharReader::Factory const&,
- JSONCPP_ISTREAM&,
- Value* root, std::string* errs);
+ * Someday we might have a real StreamReader, but for now this
+ * is convenient.
+ */
+bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
+ String* errs);
/** \brief Read from 'sin' into 'root'.
-
- Always keep comments from the input JSON.
-
- This can be used to read a file into a particular sub-object.
- For example:
- \code
- Json::Value root;
- cin >> root["dir"]["file"];
- cout << root;
- \endcode
- Result:
- \verbatim
- {
- "dir": {
- "file": {
- // The input stream JSON would be nested here.
- }
- }
- }
- \endverbatim
- \throw std::exception on parse error.
- \see Json::operator<<()
-*/
-JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
+ *
+ * Always keep comments from the input JSON.
+ *
+ * This can be used to read a file into a particular sub-object.
+ * For example:
+ * \code
+ * Json::Value root;
+ * cin >> root["dir"]["file"];
+ * cout << root;
+ * \endcode
+ * Result:
+ * \verbatim
+ * {
+ * "dir": {
+ * "file": {
+ * // The input stream JSON would be nested here.
+ * }
+ * }
+ * }
+ * \endverbatim
+ * \throw std::exception on parse error.
+ * \see Json::operator<<()
+ */
+JSON_API IStream& operator>>(IStream&, Value&);
} // namespace Json
@@ -412,4 +404,4 @@ JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#endif // CPPTL_JSON_READER_H_INCLUDED
+#endif // JSON_READER_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/value.h b/Utilities/cmjsoncpp/include/json/value.h
index 7b90c5a1a..952d42358 100644
--- a/Utilities/cmjsoncpp/include/json/value.h
+++ b/Utilities/cmjsoncpp/include/json/value.h
@@ -3,38 +3,49 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-#ifndef CPPTL_JSON_H_INCLUDED
-#define CPPTL_JSON_H_INCLUDED
+#ifndef JSON_H_INCLUDED
+#define JSON_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <string>
-#include <vector>
-#include <exception>
-#ifndef JSON_USE_CPPTL_SMALLMAP
-#include <map>
+// Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+#if defined(_MSC_VER) && _MSC_VER == 1800
+#define JSONCPP_NORETURN __declspec(noreturn)
#else
-#include <cpptl/smallmap.h>
+#define JSONCPP_NORETURN [[noreturn]]
#endif
-#ifdef JSON_USE_CPPTL
-#include <cpptl/forwards.h>
#endif
-//Conditional NORETURN attribute on the throw functions would:
-// a) suppress false positives from static code analysis
-// b) possibly improve optimization opportunities.
-#if !defined(JSONCPP_NORETURN)
-# if defined(_MSC_VER)
-# define JSONCPP_NORETURN __declspec(noreturn)
-# elif defined(__GNUC__)
-# define JSONCPP_NORETURN __attribute__ ((__noreturn__))
-# else
-# define JSONCPP_NORETURN
-# endif
+// Support for '= delete' with template declarations was a late addition
+// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
+// even though these declare themselves to be c++11 compilers.
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#if defined(__clang__) && defined(__apple_build_version__)
+#if __apple_build_version__ <= 8000042
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#elif defined(__clang__)
+#if __clang_major__ == 3 && __clang_minor__ <= 8
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#endif
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#define JSONCPP_TEMPLATE_DELETE = delete
+#endif
#endif
+#include <array>
+#include <exception>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -50,17 +61,19 @@
*/
namespace Json {
+#if JSON_USE_EXCEPTION
/** Base class for all exceptions we throw.
*
* We use nothing but these internally. Of course, STL can throw others.
*/
class JSON_API Exception : public std::exception {
public:
- Exception(JSONCPP_STRING const& msg);
- ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
- char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
+ Exception(String msg);
+ ~Exception() noexcept override;
+ char const* what() const noexcept override;
+
protected:
- JSONCPP_STRING msg_;
+ String msg_;
};
/** Exceptions which the user cannot easily avoid.
@@ -71,7 +84,7 @@ protected:
*/
class JSON_API RuntimeError : public Exception {
public:
- RuntimeError(JSONCPP_STRING const& msg);
+ RuntimeError(String const& msg);
};
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
@@ -82,13 +95,14 @@ public:
*/
class JSON_API LogicError : public Exception {
public:
- LogicError(JSONCPP_STRING const& msg);
+ LogicError(String const& msg);
};
+#endif
/// used internally
-JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
+JSONCPP_NORETURN void throwRuntimeError(String const& msg);
/// used internally
-JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
+JSONCPP_NORETURN void throwLogicError(String const& msg);
/** \brief Type of the value held by a Value object.
*/
@@ -111,14 +125,16 @@ enum CommentPlacement {
numberOfCommentPlacement
};
-//# ifdef JSON_USE_CPPTL
-// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
-// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
-//# endif
+/** \brief Type of precision for formatting of real values.
+ */
+enum PrecisionType {
+ significantDigits = 0, ///< we set max number of significant digits in string
+ decimalPlaces ///< we set max number of digits after "." in string
+};
/** \brief Lightweight wrapper to tag static string.
*
- * Value constructor and objectValue member assignement takes advantage of the
+ * Value constructor and objectValue member assignment takes advantage of the
* StaticString and avoid the cost of string duplication when storing the
* string or the member name.
*
@@ -167,7 +183,7 @@ private:
* The get() methods can be used to obtain default value in the case the
* required element does not exist.
*
- * It is possible to iterate over the list of a #objectValue values using
+ * It is possible to iterate over the list of member keys of an object using
* the getMemberNames() method.
*
* \note #Value string-length fit in size_t, but keys must be < 2^30.
@@ -178,73 +194,86 @@ private:
*/
class JSON_API Value {
friend class ValueIteratorBase;
+
public:
- typedef std::vector<JSONCPP_STRING> Members;
- typedef ValueIterator iterator;
- typedef ValueConstIterator const_iterator;
- typedef Json::UInt UInt;
- typedef Json::Int Int;
+ using Members = std::vector<String>;
+ using iterator = ValueIterator;
+ using const_iterator = ValueConstIterator;
+ using UInt = Json::UInt;
+ using Int = Json::Int;
#if defined(JSON_HAS_INT64)
- typedef Json::UInt64 UInt64;
- typedef Json::Int64 Int64;
+ using UInt64 = Json::UInt64;
+ using Int64 = Json::Int64;
#endif // defined(JSON_HAS_INT64)
- typedef Json::LargestInt LargestInt;
- typedef Json::LargestUInt LargestUInt;
- typedef Json::ArrayIndex ArrayIndex;
+ using LargestInt = Json::LargestInt;
+ using LargestUInt = Json::LargestUInt;
+ using ArrayIndex = Json::ArrayIndex;
- static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
- static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
- static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
+ // Required for boost integration, e. g. BOOST_TEST
+ using value_type = std::string;
+
+#if JSON_USE_NULLREF
+ // Binary compatibility kludges, do not use.
+ static const Value& null;
+ static const Value& nullRef;
+#endif
+
+ // null and nullRef are deprecated, use this instead.
+ static Value const& nullSingleton();
/// Minimum signed integer value that can be stored in a Json::Value.
- static const LargestInt minLargestInt;
+ static constexpr LargestInt minLargestInt =
+ LargestInt(~(LargestUInt(-1) / 2));
/// Maximum signed integer value that can be stored in a Json::Value.
- static const LargestInt maxLargestInt;
+ static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
/// Maximum unsigned integer value that can be stored in a Json::Value.
- static const LargestUInt maxLargestUInt;
+ static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
/// Minimum signed int value that can be stored in a Json::Value.
- static const Int minInt;
+ static constexpr Int minInt = Int(~(UInt(-1) / 2));
/// Maximum signed int value that can be stored in a Json::Value.
- static const Int maxInt;
+ static constexpr Int maxInt = Int(UInt(-1) / 2);
/// Maximum unsigned int value that can be stored in a Json::Value.
- static const UInt maxUInt;
+ static constexpr UInt maxUInt = UInt(-1);
#if defined(JSON_HAS_INT64)
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
- static const Int64 minInt64;
+ static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
- static const Int64 maxInt64;
+ static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
- static const UInt64 maxUInt64;
+ static constexpr UInt64 maxUInt64 = UInt64(-1);
#endif // defined(JSON_HAS_INT64)
-
+ /// Default precision for real value for string representation.
+ static constexpr UInt defaultRealPrecision = 17;
+ // The constant is hard-coded because some compiler have trouble
+ // converting Value::maxUInt64 to a double correctly (AIX/xlC).
+ // Assumes that UInt64 is a 64 bits integer.
+ static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
+// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
+// when using gcc and clang backend compilers. CZString
+// cannot be defined as private. See issue #486
+#ifdef __NVCC__
+public:
+#else
private:
+#endif
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
class CZString {
public:
- enum DuplicationPolicy {
- noDuplication = 0,
- duplicate,
- duplicateOnCopy
- };
+ enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy };
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
-#if JSON_HAS_RVALUE_REFERENCES
CZString(CZString&& other);
-#endif
~CZString();
CZString& operator=(const CZString& other);
-
-#if JSON_HAS_RVALUE_REFERENCES
CZString& operator=(CZString&& other);
-#endif
bool operator<(CZString const& other) const;
bool operator==(CZString const& other) const;
ArrayIndex index() const;
- //const char* c_str() const; ///< deprecated
+ // const char* c_str() const; ///< deprecated
char const* data() const;
unsigned length() const;
bool isStaticString() const;
@@ -253,11 +282,11 @@ private:
void swap(CZString& other);
struct StringStorage {
- unsigned policy_: 2;
- unsigned length_: 30; // 1GB max
+ unsigned policy_ : 2;
+ unsigned length_ : 30; // 1GB max
};
- char const* cstr_; // actually, a prefixed string, unless policy is noDup
+ char const* cstr_; // actually, a prefixed string, unless policy is noDup
union {
ArrayIndex index_;
StringStorage storage_;
@@ -265,29 +294,26 @@ private:
};
public:
-#ifndef JSON_USE_CPPTL_SMALLMAP
typedef std::map<CZString, Value> ObjectValues;
-#else
- typedef CppTL::SmallMap<CZString, Value> ObjectValues;
-#endif // ifndef JSON_USE_CPPTL_SMALLMAP
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public:
- /** \brief Create a default Value of the given type.
-
- This is a very useful constructor.
- To create an empty array, pass arrayValue.
- To create an empty object, pass objectValue.
- Another Value can then be set to this one by assignment.
-This is useful since clear() and resize() will not alter types.
-
- Examples:
-\code
-Json::Value null_value; // null
-Json::Value arr_value(Json::arrayValue); // []
-Json::Value obj_value(Json::objectValue); // {}
-\endcode
- */
+ /**
+ * \brief Create a default Value of the given type.
+ *
+ * This is a very useful constructor.
+ * To create an empty array, pass arrayValue.
+ * To create an empty object, pass objectValue.
+ * Another Value can then be set to this one by assignment.
+ * This is useful since clear() and resize() will not alter types.
+ *
+ * Examples:
+ * \code
+ * Json::Value null_value; // null
+ * Json::Value arr_value(Json::arrayValue); // []
+ * Json::Value obj_value(Json::objectValue); // {}
+ * \endcode
+ */
Value(ValueType type = nullValue);
Value(Int value);
Value(UInt value);
@@ -298,38 +324,35 @@ Json::Value obj_value(Json::objectValue); // {}
Value(double value);
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
- /** \brief Constructs a value from a static string.
-
+ /**
+ * \brief Constructs a value from a static string.
+ *
* Like other value string constructor but do not duplicate the string for
- * internal storage. The given string must remain alive after the call to this
- * constructor.
+ * internal storage. The given string must remain alive after the call to
+ * this constructor.
+ *
* \note This works only for null-terminated strings. (We cannot change the
- * size of this class, so we have nowhere to store the length,
- * which might be computed later for various operations.)
+ * size of this class, so we have nowhere to store the length, which might be
+ * computed later for various operations.)
*
* Example of usage:
- * \code
- * static StaticString foo("some text");
- * Json::Value aValue(foo);
- * \endcode
+ * \code
+ * static StaticString foo("some text");
+ * Json::Value aValue(foo);
+ * \endcode
*/
Value(const StaticString& value);
- Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
-#ifdef JSON_USE_CPPTL
- Value(const CppTL::ConstString& value);
-#endif
+ Value(const String& value);
Value(bool value);
- /// Deep copy.
+ Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
-#if JSON_HAS_RVALUE_REFERENCES
- /// Move constructor
Value(Value&& other);
-#endif
~Value();
- /// Deep copy, then swap(other).
- /// \note Over-write existing comments. To preserve comments, use #swapPayload().
- Value& operator=(Value other);
+ /// \note Overwrite existing comments. To preserve comments, use
+ /// #swapPayload().
+ Value& operator=(const Value& other);
+ Value& operator=(Value&& other);
/// Swap everything.
void swap(Value& other);
@@ -354,17 +377,14 @@ Json::Value obj_value(Json::objectValue); // {}
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
#if JSONCPP_USING_SECURE_MEMORY
- unsigned getCStringLength() const; //Allows you to understand the length of the CString
+ unsigned getCStringLength() const; // Allows you to understand the length of
+ // the CString
#endif
- JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
+ String asString() const; ///< Embedded zeroes are possible.
/** Get raw char* of string-value.
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
- bool getString(
- char const** begin, char const** end) const;
-#ifdef JSON_USE_CPPTL
- CppTL::ConstString asConstString() const;
-#endif
+ bool getString(char const** begin, char const** end) const;
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
@@ -390,6 +410,10 @@ Json::Value obj_value(Json::objectValue); // {}
bool isArray() const;
bool isObject() const;
+ /// The `as<T>` and `is<T>` member function templates and specializations.
+ template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
+ template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
+
bool isConvertibleTo(ValueType other) const;
/// Number of values in array or object
@@ -399,50 +423,41 @@ Json::Value obj_value(Json::objectValue); // {}
/// otherwise, false.
bool empty() const;
- /// Return isNull()
- bool operator!() const;
+ /// Return !isNull()
+ explicit operator bool() const;
/// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue
/// \post type() is unchanged
void clear();
- /// Resize the array to size elements.
+ /// Resize the array to newSize elements.
/// New elements are initialized to null.
/// May only be called on nullValue or arrayValue.
/// \pre type() is arrayValue or nullValue
/// \post type() is arrayValue
- void resize(ArrayIndex size);
+ void resize(ArrayIndex newSize);
- /// Access an array element (zero based index ).
- /// If the array contains less than index element, then null value are
- /// inserted
- /// in the array so that its size is index+1.
+ //@{
+ /// Access an array element (zero based index). If the array contains less
+ /// than index element, then null value are inserted in the array so that
+ /// its size is index+1.
/// (You may need to say 'value[0u]' to get your compiler to distinguish
- /// this from the operator[] which takes a string.)
+ /// this from the operator[] which takes a string.)
Value& operator[](ArrayIndex index);
-
- /// Access an array element (zero based index ).
- /// If the array contains less than index element, then null value are
- /// inserted
- /// in the array so that its size is index+1.
- /// (You may need to say 'value[0u]' to get your compiler to distinguish
- /// this from the operator[] which takes a string.)
Value& operator[](int index);
+ //@}
- /// Access an array element (zero based index )
+ //@{
+ /// Access an array element (zero based index).
/// (You may need to say 'value[0u]' to get your compiler to distinguish
- /// this from the operator[] which takes a string.)
+ /// this from the operator[] which takes a string.)
const Value& operator[](ArrayIndex index) const;
-
- /// Access an array element (zero based index )
- /// (You may need to say 'value[0u]' to get your compiler to distinguish
- /// this from the operator[] which takes a string.)
const Value& operator[](int index) const;
+ //@}
/// If the array contains at least index+1 elements, returns the element
- /// value,
- /// otherwise returns defaultValue.
+ /// value, otherwise returns defaultValue.
Value get(ArrayIndex index, const Value& defaultValue) const;
/// Return true if index < size().
bool isValidIndex(ArrayIndex index) const;
@@ -450,61 +465,51 @@ Json::Value obj_value(Json::objectValue); // {}
///
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value);
-
-#if JSON_HAS_RVALUE_REFERENCES
Value& append(Value&& value);
-#endif
+
+ /// \brief Insert value in array at specific index
+ bool insert(ArrayIndex index, const Value& newValue);
+ bool insert(ArrayIndex index, Value&& newValue);
/// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
- /// Exceeding that will cause an exception.
+ /// Exceeding that will cause an exception.
Value& operator[](const char* key);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const char* key) const;
/// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
- Value& operator[](const JSONCPP_STRING& key);
+ Value& operator[](const String& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
- const Value& operator[](const JSONCPP_STRING& key) const;
+ const Value& operator[](const String& key) const;
/** \brief Access an object value by name, create a null member if it does not
- exist.
-
- * If the object has no entry for that name, then the member name used to store
- * the new entry is not duplicated.
+ * exist.
+ *
+ * If the object has no entry for that name, then the member name used to
+ * store the new entry is not duplicated.
* Example of use:
- * \code
- * Json::Value object;
- * static const StaticString code("code");
- * object[code] = 1234;
- * \endcode
+ * \code
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
*/
Value& operator[](const StaticString& key);
-#ifdef JSON_USE_CPPTL
- /// Access an object value by name, create a null member if it does not exist.
- Value& operator[](const CppTL::ConstString& key);
- /// Access an object value by name, returns null if there is no member with
- /// that name.
- const Value& operator[](const CppTL::ConstString& key) const;
-#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \note key may contain embedded nulls.
- Value get(const char* begin, const char* end, const Value& defaultValue) const;
+ Value get(const char* begin, const char* end,
+ const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
- Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
-#ifdef JSON_USE_CPPTL
- /// Return the member named key if it exist, defaultValue otherwise.
- /// \note deep copy
- Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
-#endif
+ Value get(const String& key, const Value& defaultValue) const;
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@@ -512,53 +517,44 @@ Json::Value obj_value(Json::objectValue); // {}
/// Most general and efficient version of object-mutators.
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
- Value const* demand(char const* begin, char const* end);
+ Value* demand(char const* begin, char const* end);
/// \brief Remove and return the named member.
///
/// Do nothing if it did not exist.
- /// \return the removed Value, or null.
/// \pre type() is objectValue or nullValue
/// \post type() is unchanged
- /// deprecated
- JSONCPP_DEPRECATED("")
- Value removeMember(const char* key);
+ void removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
- /// deprecated
- JSONCPP_DEPRECATED("")
- Value removeMember(const JSONCPP_STRING& key);
+ void removeMember(const String& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/** \brief Remove the named map member.
-
- Update 'removed' iff removed.
- \param key may contain embedded nulls.
- \return true iff removed (no exceptions)
- */
- bool removeMember(JSONCPP_STRING const& key, Value* removed);
- /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
+ *
+ * Update 'removed' iff removed.
+ * \param key may contain embedded nulls.
+ * \return true iff removed (no exceptions)
+ */
+ bool removeMember(String const& key, Value* removed);
+ /// Same as removeMember(String const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
/** \brief Remove the indexed array element.
-
- O(n) expensive operations.
- Update 'removed' iff removed.
- \return true iff removed (no exceptions)
- */
- bool removeIndex(ArrayIndex i, Value* removed);
+ *
+ * O(n) expensive operations.
+ * Update 'removed' iff removed.
+ * \return true if removed (no exceptions)
+ */
+ bool removeIndex(ArrayIndex index, Value* removed);
/// Return true if the object has a member named key.
/// \note 'key' must be null-terminated.
bool isMember(const char* key) const;
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
- bool isMember(const JSONCPP_STRING& key) const;
- /// Same as isMember(JSONCPP_STRING const& key)const
+ bool isMember(const String& key) const;
+ /// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const;
-#ifdef JSON_USE_CPPTL
- /// Return true if the object has a member named key.
- bool isMember(const CppTL::ConstString& key) const;
-#endif
/// \brief Return a list of the member names.
///
@@ -567,23 +563,22 @@ Json::Value obj_value(Json::objectValue); // {}
/// \post if type() was nullValue, it remains nullValue
Members getMemberNames() const;
- //# ifdef JSON_USE_CPPTL
- // EnumMemberNames enumMemberNames() const;
- // EnumValues enumValues() const;
- //# endif
-
/// deprecated Always pass len.
- JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
- void setComment(const char* comment, CommentPlacement placement);
+ JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
+ void setComment(const char* comment, CommentPlacement placement) {
+ setComment(String(comment, strlen(comment)), placement);
+ }
/// Comments must be //... or /* ... */
- void setComment(const char* comment, size_t len, CommentPlacement placement);
+ void setComment(const char* comment, size_t len, CommentPlacement placement) {
+ setComment(String(comment, len), placement);
+ }
/// Comments must be //... or /* ... */
- void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
+ void setComment(String comment, CommentPlacement placement);
bool hasComment(CommentPlacement placement) const;
/// Include delimiters and embedded newlines.
- JSONCPP_STRING getComment(CommentPlacement placement) const;
+ String getComment(CommentPlacement placement) const;
- JSONCPP_STRING toStyledString() const;
+ String toStyledString() const;
const_iterator begin() const;
const_iterator end() const;
@@ -599,20 +594,20 @@ Json::Value obj_value(Json::objectValue); // {}
ptrdiff_t getOffsetLimit() const;
private:
+ void setType(ValueType v) {
+ bits_.value_type_ = static_cast<unsigned char>(v);
+ }
+ bool isAllocated() const { return bits_.allocated_; }
+ void setIsAllocated(bool v) { bits_.allocated_ = v; }
+
void initBasic(ValueType type, bool allocated = false);
+ void dupPayload(const Value& other);
+ void releasePayload();
+ void dupMeta(const Value& other);
Value& resolveReference(const char* key);
Value& resolveReference(const char* key, const char* end);
- struct CommentInfo {
- CommentInfo();
- ~CommentInfo();
-
- void setComment(const char* text, size_t len);
-
- char* comment_;
- };
-
// struct MemberNamesTransform
//{
// typedef const char *result_type;
@@ -627,13 +622,33 @@ private:
LargestUInt uint_;
double real_;
bool bool_;
- char* string_; // actually ptr to unsigned, followed by str, unless !allocated_
+ char* string_; // if allocated_, ptr to { unsigned, char[] }.
ObjectValues* map_;
} value_;
- ValueType type_ : 8;
- unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
- // If not allocated_, string_ must be null-terminated.
- CommentInfo* comments_;
+
+ struct {
+ // Really a ValueType, but types should agree for bitfield packing.
+ unsigned int value_type_ : 8;
+ // Unless allocated_, string_ must be null-terminated.
+ unsigned int allocated_ : 1;
+ } bits_;
+
+ class Comments {
+ public:
+ Comments() = default;
+ Comments(const Comments& that);
+ Comments(Comments&& that);
+ Comments& operator=(const Comments& that);
+ Comments& operator=(Comments&& that);
+ bool has(CommentPlacement slot) const;
+ String get(CommentPlacement slot) const;
+ void set(CommentPlacement slot, String comment);
+
+ private:
+ using Array = std::array<String, numberOfCommentPlacement>;
+ std::unique_ptr<Array> ptr_;
+ };
+ Comments comments_;
// [start, limit) byte offsets in the source JSON text from which this Value
// was extracted.
@@ -641,6 +656,36 @@ private:
ptrdiff_t limit_;
};
+template <> inline bool Value::as<bool>() const { return asBool(); }
+template <> inline bool Value::is<bool>() const { return isBool(); }
+
+template <> inline Int Value::as<Int>() const { return asInt(); }
+template <> inline bool Value::is<Int>() const { return isInt(); }
+
+template <> inline UInt Value::as<UInt>() const { return asUInt(); }
+template <> inline bool Value::is<UInt>() const { return isUInt(); }
+
+#if defined(JSON_HAS_INT64)
+template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
+template <> inline bool Value::is<Int64>() const { return isInt64(); }
+
+template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
+template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
+#endif
+
+template <> inline double Value::as<double>() const { return asDouble(); }
+template <> inline bool Value::is<double>() const { return isDouble(); }
+
+template <> inline String Value::as<String>() const { return asString(); }
+template <> inline bool Value::is<String>() const { return isString(); }
+
+/// These `as` specializations are type conversions, and do not have a
+/// corresponding `is`.
+template <> inline float Value::as<float>() const { return asFloat(); }
+template <> inline const char* Value::as<const char*>() const {
+ return asCString();
+}
+
/** \brief Experimental and untested: represents an element of the "path" to
* access a node.
*/
@@ -651,17 +696,13 @@ public:
PathArgument();
PathArgument(ArrayIndex index);
PathArgument(const char* key);
- PathArgument(const JSONCPP_STRING& key);
+ PathArgument(String key);
private:
- enum Kind {
- kindNone = 0,
- kindIndex,
- kindKey
- };
- JSONCPP_STRING key_;
- ArrayIndex index_;
- Kind kind_;
+ enum Kind { kindNone = 0, kindIndex, kindKey };
+ String key_;
+ ArrayIndex index_{};
+ Kind kind_{kindNone};
};
/** \brief Experimental and untested: represents a "path" to access a node.
@@ -673,12 +714,11 @@ private:
* - ".name1.name2.name3"
* - ".[0][1][2].name1[3]"
* - ".%" => member name is provided as parameter
- * - ".[%]" => index is provied as parameter
+ * - ".[%]" => index is provided as parameter
*/
class JSON_API Path {
public:
- Path(const JSONCPP_STRING& path,
- const PathArgument& a1 = PathArgument(),
+ Path(const String& path, const PathArgument& a1 = PathArgument(),
const PathArgument& a2 = PathArgument(),
const PathArgument& a3 = PathArgument(),
const PathArgument& a4 = PathArgument(),
@@ -691,15 +731,13 @@ public:
Value& make(Value& root) const;
private:
- typedef std::vector<const PathArgument*> InArgs;
- typedef std::vector<PathArgument> Args;
+ using InArgs = std::vector<const PathArgument*>;
+ using Args = std::vector<PathArgument>;
- void makePath(const JSONCPP_STRING& path, const InArgs& in);
- void addPathInArg(const JSONCPP_STRING& path,
- const InArgs& in,
- InArgs::const_iterator& itInArg,
- PathArgument::Kind kind);
- void invalidPath(const JSONCPP_STRING& path, int location);
+ void makePath(const String& path, const InArgs& in);
+ void addPathInArg(const String& path, const InArgs& in,
+ InArgs::const_iterator& itInArg, PathArgument::Kind kind);
+ static void invalidPath(const String& path, int location);
Args args_;
};
@@ -709,10 +747,10 @@ private:
*/
class JSON_API ValueIteratorBase {
public:
- typedef std::bidirectional_iterator_tag iterator_category;
- typedef unsigned int size_t;
- typedef int difference_type;
- typedef ValueIteratorBase SelfType;
+ using iterator_category = std::bidirectional_iterator_tag;
+ using size_t = unsigned int;
+ using difference_type = int;
+ using SelfType = ValueIteratorBase;
bool operator==(const SelfType& other) const { return isEqual(other); }
@@ -726,17 +764,19 @@ public:
/// Value.
Value key() const;
- /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+ /// Return the index of the referenced Value, or -1 if it is not an
+ /// arrayValue.
UInt index() const;
/// Return the member name of the referenced Value, or "" if it is not an
/// objectValue.
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
- JSONCPP_STRING name() const;
+ String name() const;
/// Return the member name of the referenced Value. "" if it is not an
/// objectValue.
- /// deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+ /// deprecated This cannot be used for UTF-8 strings, since there can be
+ /// embedded nulls.
JSONCPP_DEPRECATED("Use `key = name();` instead.")
char const* memberName() const;
/// Return the member name of the referenced Value, or NULL if it is not an
@@ -745,7 +785,14 @@ public:
char const* memberName(char const** end) const;
protected:
- Value& deref() const;
+ /*! Internal utility functions to assist with implementing
+ * other iterator functions. The const and non-const versions
+ * of the "deref" protected methods expose the protected
+ * current_ member variable in a way that can often be
+ * optimized away by the compiler.
+ */
+ const Value& deref() const;
+ Value& deref();
void increment();
@@ -760,7 +807,7 @@ protected:
private:
Value::ObjectValues::iterator current_;
// Indicates that iterator is for a null value.
- bool isNull_;
+ bool isNull_{true};
public:
// For some reason, BORLAND needs these at the end, rather
@@ -776,20 +823,21 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
friend class Value;
public:
- typedef const Value value_type;
- //typedef unsigned int size_t;
- //typedef int difference_type;
- typedef const Value& reference;
- typedef const Value* pointer;
- typedef ValueConstIterator SelfType;
+ using value_type = const Value;
+ // typedef unsigned int size_t;
+ // typedef int difference_type;
+ using reference = const Value&;
+ using pointer = const Value*;
+ using SelfType = ValueConstIterator;
ValueConstIterator();
ValueConstIterator(ValueIterator const& other);
private:
-/*! internal Use by Value to create an iterator.
- */
+ /*! internal Use by Value to create an iterator.
+ */
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+
public:
SelfType& operator=(const ValueIteratorBase& other);
@@ -826,21 +874,22 @@ class JSON_API ValueIterator : public ValueIteratorBase {
friend class Value;
public:
- typedef Value value_type;
- typedef unsigned int size_t;
- typedef int difference_type;
- typedef Value& reference;
- typedef Value* pointer;
- typedef ValueIterator SelfType;
+ using value_type = Value;
+ using size_t = unsigned int;
+ using difference_type = int;
+ using reference = Value&;
+ using pointer = Value*;
+ using SelfType = ValueIterator;
ValueIterator();
explicit ValueIterator(const ValueConstIterator& other);
ValueIterator(const ValueIterator& other);
private:
-/*! internal Use by Value to create an iterator.
- */
+ /*! internal Use by Value to create an iterator.
+ */
explicit ValueIterator(const Value::ObjectValues::iterator& current);
+
public:
SelfType& operator=(const SelfType& other);
@@ -866,19 +915,18 @@ public:
return *this;
}
- reference operator*() const { return deref(); }
-
- pointer operator->() const { return &deref(); }
+ /*! The return value of non-const iterators can be
+ * changed, so the these functions are not const
+ * because the returned references/pointers can be used
+ * to change state of the base class.
+ */
+ reference operator*() { return deref(); }
+ pointer operator->() { return &deref(); }
};
-} // namespace Json
+inline void swap(Value& a, Value& b) { a.swap(b); }
-
-namespace std {
-/// Specialize std::swap() for Json::Value.
-template<>
-inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
-}
+} // namespace Json
#if !defined(__SUNPRO_CC)
#pragma pack(pop)
@@ -888,4 +936,4 @@ inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#endif // CPPTL_JSON_H_INCLUDED
+#endif // JSON_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/include/json/version.h b/Utilities/cmjsoncpp/include/json/version.h
index d95396189..5b9783d96 100644
--- a/Utilities/cmjsoncpp/include/json/version.h
+++ b/Utilities/cmjsoncpp/include/json/version.h
@@ -1,14 +1,22 @@
-// DO NOT EDIT. This file (and "version") is generated by CMake.
-// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
-# define JSON_VERSION_H_INCLUDED
+#define JSON_VERSION_H_INCLUDED
-# define JSONCPP_VERSION_STRING "1.8.2"
-# define JSONCPP_VERSION_MAJOR 1
-# define JSONCPP_VERSION_MINOR 8
-# define JSONCPP_VERSION_PATCH 2
-# define JSONCPP_VERSION_QUALIFIER
-# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.4"
+#define JSONCPP_VERSION_MAJOR 1
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 3
+#define JSONCPP_VERSION_QUALIFIER
+#define JSONCPP_VERSION_HEXA \
+ ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
+ (JSONCPP_VERSION_PATCH << 8))
#ifdef JSONCPP_USING_SECURE_MEMORY
#undef JSONCPP_USING_SECURE_MEMORY
diff --git a/Utilities/cmjsoncpp/include/json/writer.h b/Utilities/cmjsoncpp/include/json/writer.h
index d3ae62b28..cc6b78c9f 100644
--- a/Utilities/cmjsoncpp/include/json/writer.h
+++ b/Utilities/cmjsoncpp/include/json/writer.h
@@ -9,14 +9,13 @@
#if !defined(JSON_IS_AMALGAMATION)
#include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <iosfwd>
-#include <vector>
-#include <string>
#include <ostream>
+#include <string>
+#include <vector>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -30,31 +29,31 @@ namespace Json {
class Value;
/**
-
-Usage:
-\code
- using namespace Json;
- void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
- std::unique_ptr<StreamWriter> const writer(
- factory.newStreamWriter());
- writer->write(value, &std::cout);
- std::cout << std::endl; // add lf and flush
- }
-\endcode
-*/
+ *
+ * Usage:
+ * \code
+ * using namespace Json;
+ * void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
+ * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
+ * writer->write(value, &std::cout);
+ * std::cout << std::endl; // add lf and flush
+ * }
+ * \endcode
+ */
class JSON_API StreamWriter {
protected:
- JSONCPP_OSTREAM* sout_; // not owned; will not delete
+ OStream* sout_; // not owned; will not delete
public:
StreamWriter();
virtual ~StreamWriter();
/** Write Value into document as configured in sub-class.
- Do not take ownership of sout, but maintain a reference during function.
- \pre sout != NULL
- \return zero on success (For now, we always return zero, so check the stream instead.)
- \throw std::exception possibly, depending on configuration
+ * Do not take ownership of sout, but maintain a reference during function.
+ * \pre sout != NULL
+ * \return zero on success (For now, we always return zero, so check the
+ * stream instead.) \throw std::exception possibly, depending on
+ * configuration
*/
- virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
+ virtual int write(Value const& root, OStream* sout) = 0;
/** \brief A simple abstract factory.
*/
@@ -65,64 +64,69 @@ public:
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
virtual StreamWriter* newStreamWriter() const = 0;
- }; // Factory
-}; // StreamWriter
+ }; // Factory
+}; // StreamWriter
/** \brief Write into stringstream, then return string, for convenience.
* A StreamWriter will be created from the factory, used, and then deleted.
*/
-JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
-
+String JSON_API writeString(StreamWriter::Factory const& factory,
+ Value const& root);
/** \brief Build a StreamWriter implementation.
-Usage:
-\code
- using namespace Json;
- Value value = ...;
- StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = " "; // or whatever you like
- std::unique_ptr<Json::StreamWriter> writer(
- builder.newStreamWriter());
- writer->write(value, &std::cout);
- std::cout << std::endl; // add lf and flush
-\endcode
+* Usage:
+* \code
+* using namespace Json;
+* Value value = ...;
+* StreamWriterBuilder builder;
+* builder["commentStyle"] = "None";
+* builder["indentation"] = " "; // or whatever you like
+* std::unique_ptr<Json::StreamWriter> writer(
+* builder.newStreamWriter());
+* writer->write(value, &std::cout);
+* std::cout << std::endl; // add lf and flush
+* \endcode
*/
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
public:
// Note: We use a Json::Value so that we can add data-members to this class
// without a major version bump.
/** Configuration of this builder.
- Available settings (case-sensitive):
- - "commentStyle": "None" or "All"
- - "indentation": "<anything>"
- - "enableYAMLCompatibility": false or true
- - slightly change the whitespace around colons
- - "dropNullPlaceholders": false or true
- - Drop the "null" string from the writer's output for nullValues.
- Strictly speaking, this is not valid JSON. But when the output is being
- fed to a browser's Javascript, it makes for smaller output and the
- browser can handle the output just fine.
- - "useSpecialFloats": false or true
- - If true, outputs non-finite floating point values in the following way:
- NaN values as "NaN", positive infinity as "Infinity", and negative infinity
- as "-Infinity".
-
- You can examine 'settings_` yourself
- to see the defaults. You can also write and read them just like any
- JSON Value.
- \sa setDefaults()
- */
+ * Available settings (case-sensitive):
+ * - "commentStyle": "None" or "All"
+ * - "indentation": "<anything>".
+ * - Setting this to an empty string also omits newline characters.
+ * - "enableYAMLCompatibility": false or true
+ * - slightly change the whitespace around colons
+ * - "dropNullPlaceholders": false or true
+ * - Drop the "null" string from the writer's output for nullValues.
+ * Strictly speaking, this is not valid JSON. But when the output is being
+ * fed to a browser's JavaScript, it makes for smaller output and the
+ * browser can handle the output just fine.
+ * - "useSpecialFloats": false or true
+ * - If true, outputs non-finite floating point values in the following way:
+ * NaN values as "NaN", positive infinity as "Infinity", and negative
+ * infinity as "-Infinity".
+ * - "precision": int
+ * - Number of precision digits for formatting of real values.
+ * - "precisionType": "significant"(default) or "decimal"
+ * - Type of precision for formatting of real values.
+
+ * You can examine 'settings_` yourself
+ * to see the defaults. You can also write and read them just like any
+ * JSON Value.
+ * \sa setDefaults()
+ */
Json::Value settings_;
StreamWriterBuilder();
- ~StreamWriterBuilder() JSONCPP_OVERRIDE;
+ ~StreamWriterBuilder() override;
/**
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
- StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
+ StreamWriter* newStreamWriter() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
@@ -130,7 +134,7 @@ public:
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
- Value& operator[](JSONCPP_STRING key);
+ Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
@@ -147,7 +151,7 @@ class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
public:
virtual ~Writer();
- virtual JSONCPP_STRING write(const Value& root) = 0;
+ virtual String write(const Value& root) = 0;
};
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
@@ -155,21 +159,25 @@ public:
*
* The JSON document is written in a single line. It is not intended for 'human'
*consumption,
- * but may be usefull to support feature such as RPC where bandwith is limited.
+ * but may be useful to support feature such as RPC where bandwidth is limited.
* \sa Reader, Value
* deprecated Use StreamWriterBuilder.
*/
-class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
-
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
+ : public Writer {
public:
FastWriter();
- ~FastWriter() JSONCPP_OVERRIDE {}
+ ~FastWriter() override = default;
void enableYAMLCompatibility();
/** \brief Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being
- * fed to a browser's Javascript, it makes for smaller output and the
+ * fed to a browser's JavaScript, it makes for smaller output and the
* browser can handle the output just fine.
*/
void dropNullPlaceholders();
@@ -177,16 +185,19 @@ public:
void omitEndingLineFeed();
public: // overridden from Writer
- JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+ String write(const Value& root) override;
private:
void writeValue(const Value& value);
- JSONCPP_STRING document_;
- bool yamlCompatiblityEnabled_;
- bool dropNullPlaceholders_;
- bool omitEndingLineFeed_;
+ String document_;
+ bool yamlCompatibilityEnabled_{false};
+ bool dropNullPlaceholders_{false};
+ bool omitEndingLineFeed_{false};
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
*human friendly way.
@@ -212,41 +223,49 @@ private:
* \sa Reader, Value, Value::setComment()
* deprecated Use StreamWriterBuilder.
*/
-class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
+ StyledWriter : public Writer {
public:
StyledWriter();
- ~StyledWriter() JSONCPP_OVERRIDE {}
+ ~StyledWriter() override = default;
public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize.
* \return String containing the JSON document that represents the root value.
*/
- JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+ String write(const Value& root) override;
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
- bool isMultineArray(const Value& value);
- void pushValue(const JSONCPP_STRING& value);
+ bool isMultilineArray(const Value& value);
+ void pushValue(const String& value);
void writeIndent();
- void writeWithIndent(const JSONCPP_STRING& value);
+ void writeWithIndent(const String& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
- bool hasCommentForValue(const Value& value);
- static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+ static bool hasCommentForValue(const Value& value);
+ static String normalizeEOL(const String& text);
- typedef std::vector<JSONCPP_STRING> ChildValues;
+ using ChildValues = std::vector<String>;
ChildValues childValues_;
- JSONCPP_STRING document_;
- JSONCPP_STRING indentString_;
- unsigned int rightMargin_;
- unsigned int indentSize_;
- bool addChildValues_;
+ String document_;
+ String indentString_;
+ unsigned int rightMargin_{74};
+ unsigned int indentSize_{3};
+ bool addChildValues_{false};
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
human friendly way,
@@ -273,13 +292,18 @@ private:
* \sa Reader, Value, Value::setComment()
* deprecated Use StreamWriterBuilder.
*/
-class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
+ StyledStreamWriter {
public:
-/**
- * \param indentation Each level will be indented by this amount extra.
- */
- StyledStreamWriter(JSONCPP_STRING indentation = "\t");
- ~StyledStreamWriter() {}
+ /**
+ * \param indentation Each level will be indented by this amount extra.
+ */
+ StyledStreamWriter(String indentation = "\t");
+ ~StyledStreamWriter() = default;
public:
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
@@ -288,46 +312,51 @@ public:
* \note There is no point in deriving from Writer, since write() should not
* return a value.
*/
- void write(JSONCPP_OSTREAM& out, const Value& root);
+ void write(OStream& out, const Value& root);
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
- bool isMultineArray(const Value& value);
- void pushValue(const JSONCPP_STRING& value);
+ bool isMultilineArray(const Value& value);
+ void pushValue(const String& value);
void writeIndent();
- void writeWithIndent(const JSONCPP_STRING& value);
+ void writeWithIndent(const String& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
- bool hasCommentForValue(const Value& value);
- static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+ static bool hasCommentForValue(const Value& value);
+ static String normalizeEOL(const String& text);
- typedef std::vector<JSONCPP_STRING> ChildValues;
+ using ChildValues = std::vector<String>;
ChildValues childValues_;
- JSONCPP_OSTREAM* document_;
- JSONCPP_STRING indentString_;
- unsigned int rightMargin_;
- JSONCPP_STRING indentation_;
+ OStream* document_;
+ String indentString_;
+ unsigned int rightMargin_{74};
+ String indentation_;
bool addChildValues_ : 1;
bool indented_ : 1;
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
#if defined(JSON_HAS_INT64)
-JSONCPP_STRING JSON_API valueToString(Int value);
-JSONCPP_STRING JSON_API valueToString(UInt value);
+String JSON_API valueToString(Int value);
+String JSON_API valueToString(UInt value);
#endif // if defined(JSON_HAS_INT64)
-JSONCPP_STRING JSON_API valueToString(LargestInt value);
-JSONCPP_STRING JSON_API valueToString(LargestUInt value);
-JSONCPP_STRING JSON_API valueToString(double value);
-JSONCPP_STRING JSON_API valueToString(bool value);
-JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
+String JSON_API valueToString(LargestInt value);
+String JSON_API valueToString(LargestUInt value);
+String JSON_API valueToString(
+ double value, unsigned int precision = Value::defaultRealPrecision,
+ PrecisionType precisionType = PrecisionType::significantDigits);
+String JSON_API valueToString(bool value);
+String JSON_API valueToQuotedString(const char* value);
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()
-JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
+JSON_API OStream& operator<<(OStream&, const Value& root);
} // namespace Json
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
index 8291cc654..e6caf403b 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp
@@ -5,69 +5,65 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
+#include "json_tool.h"
#include <json/assertions.h>
#include <json/reader.h>
#include <json/value.h>
-#include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <utility>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iostream>
#include <istream>
-#include <sstream>
+#include <limits>
#include <memory>
#include <set>
-#include <limits>
+#include <sstream>
+#include <utility>
-#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
-#endif
+#include <cstdio>
+#if __cplusplus >= 201103L
-#if defined(__QNXNTO__)
+#if !defined(sscanf)
#define sscanf std::sscanf
#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+#endif //__cplusplus
+
+#if defined(_MSC_VER)
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+#endif //_MSC_VER
+
+#if defined(_MSC_VER)
// Disable warning about strdup being deprecated.
#pragma warning(disable : 4996)
#endif
-// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
+// time to change the stack limit
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
#endif
-static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+static size_t const stackLimit_g =
+ JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<CharReader> CharReaderPtr;
+using CharReaderPtr = std::unique_ptr<CharReader>;
#else
-typedef std::auto_ptr<CharReader> CharReaderPtr;
+using CharReaderPtr = std::auto_ptr<CharReader>;
#endif
// Implementation of class Features
// ////////////////////////////////
-Features::Features()
- : allowComments_(true), strictRoot_(false),
- allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+Features::Features() = default;
-Features Features::all() { return Features(); }
+Features Features::all() { return {}; }
Features Features::strictMode() {
Features features;
@@ -82,49 +78,38 @@ Features Features::strictMode() {
// ////////////////////////////////
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
- for (; begin < end; ++begin)
- if (*begin == '\n' || *begin == '\r')
- return true;
- return false;
+ return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
}
// Class Reader
// //////////////////////////////////////////////////////////////////
-Reader::Reader()
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(), features_(Features::all()),
- collectComments_() {}
+Reader::Reader() : features_(Features::all()) {}
-Reader::Reader(const Features& features)
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(), features_(features), collectComments_() {
-}
+Reader::Reader(const Features& features) : features_(features) {}
-bool
-Reader::parse(const std::string& document, Value& root, bool collectComments) {
+bool Reader::parse(const std::string& document, Value& root,
+ bool collectComments) {
document_.assign(document.begin(), document.end());
const char* begin = document_.c_str();
const char* end = begin + document_.length();
return parse(begin, end, root, collectComments);
}
-bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
- // std::istream_iterator<char> begin(sin);
+bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
+ // std::istream_iterator<char> begin(is);
// std::istream_iterator<char> end;
// Those would allow streamed input from a file, if parse() were a
// template function.
- // Since JSONCPP_STRING is reference-counted, this at least does not
+ // Since String is reference-counted, this at least does not
// create an extra copy.
- JSONCPP_STRING doc;
- std::getline(sin, doc, (char)EOF);
+ String doc;
+ std::getline(is, doc, static_cast<char> EOF);
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
}
-bool Reader::parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
+bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
bool collectComments) {
if (!features_.allowComments_) {
collectComments = false;
@@ -134,8 +119,8 @@ bool Reader::parse(const char* beginDoc,
end_ = endDoc;
collectComments_ = collectComments;
current_ = begin_;
- lastValueEnd_ = 0;
- lastValue_ = 0;
+ lastValueEnd_ = nullptr;
+ lastValue_ = nullptr;
commentsBefore_.clear();
errors_.clear();
while (!nodes_.empty())
@@ -165,9 +150,11 @@ bool Reader::parse(const char* beginDoc,
bool Reader::readValue() {
// readValue() may call itself only if it calls readObject() or ReadArray().
- // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
- // parse() executes one nodes_.push(), so > instead of >=.
- if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+ // These methods execute nodes_.push() just before and nodes_.pop)() just
+ // after calling readValue(). parse() executes one nodes_.push(), so > instead
+ // of >=.
+ if (nodes_.size() > stackLimit_g)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
skipCommentTokens(token);
@@ -193,30 +180,24 @@ bool Reader::readValue() {
case tokenString:
successful = decodeString(token);
break;
- case tokenTrue:
- {
+ case tokenTrue: {
Value v(true);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenFalse:
- {
+ } break;
+ case tokenFalse: {
Value v(false);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNull:
- {
+ } break;
+ case tokenNull: {
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
+ } break;
case tokenArraySeparator:
case tokenObjectEnd:
case tokenArrayEnd:
@@ -322,7 +303,7 @@ bool Reader::readToken(Token& token) {
if (!ok)
token.type_ = tokenError;
token.end_ = current_;
- return true;
+ return ok;
}
void Reader::skipSpaces() {
@@ -335,7 +316,7 @@ void Reader::skipSpaces() {
}
}
-bool Reader::match(Location pattern, int patternLength) {
+bool Reader::match(const Char* pattern, int patternLength) {
if (end_ - current_ < patternLength)
return false;
int index = patternLength;
@@ -369,16 +350,16 @@ bool Reader::readComment() {
return true;
}
-JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
- JSONCPP_STRING normalized;
+String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
+ String normalized;
normalized.reserve(static_cast<size_t>(end - begin));
Reader::Location current = begin;
while (current != end) {
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -388,12 +369,12 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end
return normalized;
}
-void
-Reader::addComment(Location begin, Location end, CommentPlacement placement) {
+void Reader::addComment(Location begin, Location end,
+ CommentPlacement placement) {
assert(collectComments_);
- const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
+ const String& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
+ assert(lastValue_ != nullptr);
lastValue_->setComment(normalized, placement);
} else {
commentsBefore_ += normalized;
@@ -426,7 +407,7 @@ bool Reader::readCppStyleComment() {
}
void Reader::readNumber() {
- const char *p = current_;
+ Location p = current_;
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
@@ -459,12 +440,12 @@ bool Reader::readString() {
return c == '"';
}
-bool Reader::readObject(Token& tokenStart) {
+bool Reader::readObject(Token& token) {
Token tokenName;
- JSONCPP_STRING name;
+ String name;
Value init(objectValue);
currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ currentValue().setOffsetStart(token.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -481,15 +462,15 @@ bool Reader::readObject(Token& tokenStart) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
- name = JSONCPP_STRING(numberName.asCString());
+ name = numberName.asString();
} else {
break;
}
Token colon;
if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
+ return addErrorAndRecover("Missing ':' after object member name", colon,
+ tokenObjectEnd);
}
Value& value = currentValue()[name];
nodes_.push(&value);
@@ -502,8 +483,8 @@ bool Reader::readObject(Token& tokenStart) {
if (!readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return addErrorAndRecover("Missing ',' or '}' in object declaration",
+ comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
@@ -511,14 +492,14 @@ bool Reader::readObject(Token& tokenStart) {
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return addErrorAndRecover("Missing '}' or object member name", tokenName,
+ tokenObjectEnd);
}
-bool Reader::readArray(Token& tokenStart) {
+bool Reader::readArray(Token& token) {
Value init(arrayValue);
currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ currentValue().setOffsetStart(token.start_ - begin_);
skipSpaces();
if (current_ != end_ && *current_ == ']') // empty array
{
@@ -535,19 +516,19 @@ bool Reader::readArray(Token& tokenStart) {
if (!ok) // error already set
return recoverFromError(tokenArrayEnd);
- Token token;
+ Token currentToken;
// Accept Comment after last item in the array.
- ok = readToken(token);
- while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = readToken(currentToken);
+ while (currentToken.type_ == tokenComment && ok) {
+ ok = readToken(currentToken);
}
- bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
+ currentToken.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return addErrorAndRecover("Missing ',' or ']' in array declaration",
+ currentToken, tokenArrayEnd);
}
- if (token.type_ == tokenArrayEnd)
+ if (currentToken.type_ == tokenArrayEnd)
break;
}
return true;
@@ -571,7 +552,8 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
bool isNegative = *current == '-';
if (isNegative)
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+ // TODO: Help the compiler do the div and mod at compile time or get rid of
+ // them.
Value::LargestUInt maxIntegerValue =
isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
: Value::maxLargestUInt;
@@ -581,7 +563,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
- Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+ auto digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, b) this is the last digit, and
@@ -617,18 +599,17 @@ bool Reader::decodeDouble(Token& token) {
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
- JSONCPP_STRING buffer(token.start_, token.end_);
- JSONCPP_ISTRINGSTREAM is(buffer);
+ String buffer(token.start_, token.end_);
+ IStringStream is(buffer);
if (!(is >> value))
- return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
+ return addError(
+ "'" + String(token.start_, token.end_) + "' is not a number.", token);
decoded = value;
return true;
}
bool Reader::decodeString(Token& token) {
- JSONCPP_STRING decoded_string;
+ String decoded_string;
if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
@@ -638,7 +619,7 @@ bool Reader::decodeString(Token& token) {
return true;
}
-bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+bool Reader::decodeString(Token& token, String& decoded) {
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -646,7 +627,7 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
Char c = *current++;
if (c == '"')
break;
- else if (c == '\\') {
+ if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@@ -691,10 +672,8 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
return true;
}
-bool Reader::decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode) {
+bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode) {
if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
return false;
@@ -703,10 +682,9 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
if (end - current < 6)
return addError(
"additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
- unsigned int surrogatePair;
+ token, current);
if (*(current++) == '\\' && *(current++) == 'u') {
+ unsigned int surrogatePair;
if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
@@ -714,20 +692,17 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
} else
return addError("expecting another \\u token to begin the second half of "
"a unicode surrogate pair",
- token,
- current);
+ token, current);
}
return true;
}
-bool Reader::decodeUnicodeEscapeSequence(Token& token,
- Location& current,
+bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
Location end,
unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
+ "Bad unicode escape sequence in string: four digits expected.", token,
current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
@@ -742,15 +717,13 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
else
return addError(
"Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ token, current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool
-Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+bool Reader::addError(const String& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
@@ -772,8 +745,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) {
return false;
}
-bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
+bool Reader::addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken) {
addError(message, token);
return recoverFromError(skipUntilToken);
@@ -787,8 +759,7 @@ Reader::Char Reader::getNextChar() {
return *current_++;
}
-void Reader::getLocationLineAndColumn(Location location,
- int& line,
+void Reader::getLocationLineAndColumn(Location location, int& line,
int& column) const {
Location current = begin_;
Location lastLineStart = current;
@@ -810,25 +781,22 @@ void Reader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
+String Reader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
- snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
// Deprecated. Preserved for backward compatibility
-JSONCPP_STRING Reader::getFormatedErrorMessages() const {
+String Reader::getFormatedErrorMessages() const {
return getFormattedErrorMessages();
}
-JSONCPP_STRING Reader::getFormattedErrorMessages() const {
- JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
- const ErrorInfo& error = *itError;
+String Reader::getFormattedErrorMessages() const {
+ String formattedMessage;
+ for (const auto& error : errors_) {
formattedMessage +=
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
@@ -841,10 +809,7 @@ JSONCPP_STRING Reader::getFormattedErrorMessages() const {
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
std::vector<Reader::StructuredError> allErrors;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
- const ErrorInfo& error = *itError;
+ for (const auto& error : errors_) {
Reader::StructuredError structured;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
@@ -854,28 +819,27 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
return allErrors;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
+bool Reader::pushError(const Value& value, const String& message) {
ptrdiff_t const length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
+ token.end_ = begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
- info.extra_ = 0;
+ info.extra_ = nullptr;
errors_.push_back(info);
return true;
}
-bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
+bool Reader::pushError(const Value& value, const String& message,
+ const Value& extra) {
ptrdiff_t const length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length
- || extra.getOffsetLimit() > length)
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
+ extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
@@ -889,15 +853,15 @@ bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const
return true;
}
-bool Reader::good() const {
- return !errors_.size();
-}
+bool Reader::good() const { return errors_.empty(); }
-// exact copy of Features
+// Originally copied from the Features class (now deprecated), used internally
+// for features implementation.
class OurFeatures {
public:
static OurFeatures all();
bool allowComments_;
+ bool allowTrailingCommas_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_;
@@ -905,42 +869,36 @@ public:
bool failIfExtra_;
bool rejectDupKeys_;
bool allowSpecialFloats_;
- int stackLimit_;
-}; // OurFeatures
-
-// exact copy of Implementation of class Features
-// ////////////////////////////////
+ bool skipBom_;
+ size_t stackLimit_;
+}; // OurFeatures
-OurFeatures OurFeatures::all() { return OurFeatures(); }
+OurFeatures OurFeatures::all() { return {}; }
// Implementation of class Reader
// ////////////////////////////////
-// exact copy of Reader, renamed to OurReader
+// Originally copied from the Reader class (now deprecated), used internally
+// for implementing JSON reading.
class OurReader {
public:
- typedef char Char;
- typedef const Char* Location;
+ using Char = char;
+ using Location = const Char*;
struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
- JSONCPP_STRING message;
+ String message;
};
- OurReader(OurFeatures const& features);
- bool parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
+ explicit OurReader(OurFeatures const& features);
+ bool parse(const char* beginDoc, const char* endDoc, Value& root,
bool collectComments = true);
- JSONCPP_STRING getFormattedErrorMessages() const;
+ String getFormattedErrorMessages() const;
std::vector<StructuredError> getStructuredErrors() const;
- bool pushError(const Value& value, const JSONCPP_STRING& message);
- bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
- bool good() const;
private:
- OurReader(OurReader const&); // no impl
- void operator=(OurReader const&); // no impl
+ OurReader(OurReader const&); // no impl
+ void operator=(OurReader const&); // no impl
enum TokenType {
tokenEndOfStream = 0,
@@ -972,17 +930,18 @@ private:
class ErrorInfo {
public:
Token token_;
- JSONCPP_STRING message_;
+ String message_;
Location extra_;
};
- typedef std::deque<ErrorInfo> Errors;
+ using Errors = std::deque<ErrorInfo>;
bool readToken(Token& token);
void skipSpaces();
- bool match(Location pattern, int patternLength);
+ void skipBom(bool skipBom);
+ bool match(const Char* pattern, int patternLength);
bool readComment();
- bool readCStyleComment();
+ bool readCStyleComment(bool* containsNewLineResult);
bool readCppStyleComment();
bool readString();
bool readStringSingleQuote();
@@ -993,68 +952,57 @@ private:
bool decodeNumber(Token& token);
bool decodeNumber(Token& token, Value& decoded);
bool decodeString(Token& token);
- bool decodeString(Token& token, JSONCPP_STRING& decoded);
+ bool decodeString(Token& token, String& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
- bool decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
+ bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
unsigned int& unicode);
- bool decodeUnicodeEscapeSequence(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode);
- bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+ bool decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end, unsigned int& unicode);
+ bool addError(const String& message, Token& token, Location extra = nullptr);
bool recoverFromError(TokenType skipUntilToken);
- bool addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
+ bool addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
Value& currentValue();
Char getNextChar();
- void
- getLocationLineAndColumn(Location location, int& line, int& column) const;
- JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+ void getLocationLineAndColumn(Location location, int& line,
+ int& column) const;
+ String getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
void skipCommentTokens(Token& token);
- static JSONCPP_STRING normalizeEOL(Location begin, Location end);
+ static String normalizeEOL(Location begin, Location end);
static bool containsNewLine(Location begin, Location end);
- typedef std::stack<Value*> Nodes;
- Nodes nodes_;
- Errors errors_;
- JSONCPP_STRING document_;
- Location begin_;
- Location end_;
- Location current_;
- Location lastValueEnd_;
- Value* lastValue_;
- JSONCPP_STRING commentsBefore_;
+ using Nodes = std::stack<Value*>;
+
+ Nodes nodes_{};
+ Errors errors_{};
+ String document_{};
+ Location begin_ = nullptr;
+ Location end_ = nullptr;
+ Location current_ = nullptr;
+ Location lastValueEnd_ = nullptr;
+ Value* lastValue_ = nullptr;
+ bool lastValueHasAComment_ = false;
+ String commentsBefore_{};
OurFeatures const features_;
- bool collectComments_;
-}; // OurReader
+ bool collectComments_ = false;
+}; // OurReader
// complete copy of Read impl, for OurReader
-bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
- for (; begin < end; ++begin)
- if (*begin == '\n' || *begin == '\r')
- return true;
- return false;
+bool OurReader::containsNewLine(OurReader::Location begin,
+ OurReader::Location end) {
+ return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
}
-OurReader::OurReader(OurFeatures const& features)
- : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
- lastValue_(), commentsBefore_(),
- features_(features), collectComments_() {
-}
+OurReader::OurReader(OurFeatures const& features) : features_(features) {}
-bool OurReader::parse(const char* beginDoc,
- const char* endDoc,
- Value& root,
- bool collectComments) {
+bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments) {
if (!features_.allowComments_) {
collectComments = false;
}
@@ -1063,22 +1011,23 @@ bool OurReader::parse(const char* beginDoc,
end_ = endDoc;
collectComments_ = collectComments;
current_ = begin_;
- lastValueEnd_ = 0;
- lastValue_ = 0;
+ lastValueEnd_ = nullptr;
+ lastValue_ = nullptr;
commentsBefore_.clear();
errors_.clear();
while (!nodes_.empty())
nodes_.pop();
nodes_.push(&root);
+ // skip byte order mark if it exists at the beginning of the UTF-8 text.
+ skipBom(features_.skipBom_);
bool successful = readValue();
+ nodes_.pop();
Token token;
skipCommentTokens(token);
- if (features_.failIfExtra_) {
- if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
- addError("Extra non-whitespace after JSON value.", token);
- return false;
- }
+ if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
+ addError("Extra non-whitespace after JSON value.", token);
+ return false;
}
if (collectComments_ && !commentsBefore_.empty())
root.setComment(commentsBefore_, commentAfter);
@@ -1100,7 +1049,8 @@ bool OurReader::parse(const char* beginDoc,
bool OurReader::readValue() {
// To preserve the old behaviour we cast size_t to int.
- if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+ if (nodes_.size() > features_.stackLimit_)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
skipCommentTokens(token);
bool successful = true;
@@ -1125,54 +1075,42 @@ bool OurReader::readValue() {
case tokenString:
successful = decodeString(token);
break;
- case tokenTrue:
- {
+ case tokenTrue: {
Value v(true);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenFalse:
- {
+ } break;
+ case tokenFalse: {
Value v(false);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNull:
- {
+ } break;
+ case tokenNull: {
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNaN:
- {
+ } break;
+ case tokenNaN: {
Value v(std::numeric_limits<double>::quiet_NaN());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenPosInf:
- {
+ } break;
+ case tokenPosInf: {
Value v(std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
- case tokenNegInf:
- {
+ } break;
+ case tokenNegInf: {
Value v(-std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
- }
- break;
+ } break;
case tokenArraySeparator:
case tokenObjectEnd:
case tokenArrayEnd:
@@ -1194,6 +1132,7 @@ bool OurReader::readValue() {
if (collectComments_) {
lastValueEnd_ = current_;
+ lastValueHasAComment_ = false;
lastValue_ = &currentValue();
}
@@ -1234,10 +1173,13 @@ bool OurReader::readToken(Token& token) {
break;
case '\'':
if (features_.allowSingleQuotes_) {
- token.type_ = tokenString;
- ok = readStringSingleQuote();
+ token.type_ = tokenString;
+ ok = readStringSingleQuote();
+ } else {
+ // If we don't allow single quotes, this is a failure case.
+ ok = false;
+ }
break;
- } // else continue
case '/':
token.type_ = tokenComment;
ok = readComment();
@@ -1263,6 +1205,14 @@ bool OurReader::readToken(Token& token) {
ok = features_.allowSpecialFloats_ && match("nfinity", 7);
}
break;
+ case '+':
+ if (readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenPosInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
+ break;
case 't':
token.type_ = tokenTrue;
ok = match("rue", 3);
@@ -1307,7 +1257,7 @@ bool OurReader::readToken(Token& token) {
if (!ok)
token.type_ = tokenError;
token.end_ = current_;
- return true;
+ return ok;
}
void OurReader::skipSpaces() {
@@ -1320,7 +1270,17 @@ void OurReader::skipSpaces() {
}
}
-bool OurReader::match(Location pattern, int patternLength) {
+void OurReader::skipBom(bool skipBom) {
+ // The default behavior is to skip BOM.
+ if (skipBom) {
+ if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
+ begin_ += 3;
+ current_ = begin_;
+ }
+ }
+}
+
+bool OurReader::match(const Char* pattern, int patternLength) {
if (end_ - current_ < patternLength)
return false;
int index = patternLength;
@@ -1332,21 +1292,32 @@ bool OurReader::match(Location pattern, int patternLength) {
}
bool OurReader::readComment() {
- Location commentBegin = current_ - 1;
- Char c = getNextChar();
+ const Location commentBegin = current_ - 1;
+ const Char c = getNextChar();
bool successful = false;
- if (c == '*')
- successful = readCStyleComment();
- else if (c == '/')
+ bool cStyleWithEmbeddedNewline = false;
+
+ const bool isCStyleComment = (c == '*');
+ const bool isCppStyleComment = (c == '/');
+ if (isCStyleComment) {
+ successful = readCStyleComment(&cStyleWithEmbeddedNewline);
+ } else if (isCppStyleComment) {
successful = readCppStyleComment();
+ }
+
if (!successful)
return false;
if (collectComments_) {
CommentPlacement placement = commentBefore;
- if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
- if (c != '*' || !containsNewLine(commentBegin, current_))
- placement = commentAfterOnSameLine;
+
+ if (!lastValueHasAComment_) {
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (isCppStyleComment || !cStyleWithEmbeddedNewline) {
+ placement = commentAfterOnSameLine;
+ lastValueHasAComment_ = true;
+ }
+ }
}
addComment(commentBegin, current_, placement);
@@ -1354,16 +1325,17 @@ bool OurReader::readComment() {
return true;
}
-JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
- JSONCPP_STRING normalized;
+String OurReader::normalizeEOL(OurReader::Location begin,
+ OurReader::Location end) {
+ String normalized;
normalized.reserve(static_cast<size_t>(end - begin));
OurReader::Location current = begin;
while (current != end) {
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
- // convert dos EOL
- ++current;
+ // convert dos EOL
+ ++current;
// convert Mac EOL
normalized += '\n';
} else {
@@ -1373,24 +1345,29 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc
return normalized;
}
-void
-OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+void OurReader::addComment(Location begin, Location end,
+ CommentPlacement placement) {
assert(collectComments_);
- const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
+ const String& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
- assert(lastValue_ != 0);
+ assert(lastValue_ != nullptr);
lastValue_->setComment(normalized, placement);
} else {
commentsBefore_ += normalized;
}
}
-bool OurReader::readCStyleComment() {
+bool OurReader::readCStyleComment(bool* containsNewLineResult) {
+ *containsNewLineResult = false;
+
while ((current_ + 1) < end_) {
Char c = getNextChar();
if (c == '*' && *current_ == '/')
break;
+ if (c == '\n')
+ *containsNewLineResult = true;
}
+
return getNextChar() == '/';
}
@@ -1411,7 +1388,7 @@ bool OurReader::readCppStyleComment() {
}
bool OurReader::readNumber(bool checkInf) {
- const char *p = current_;
+ Location p = current_;
if (checkInf && p != end_ && *p == 'I') {
current_ = ++p;
return false;
@@ -1448,7 +1425,6 @@ bool OurReader::readString() {
return c == '"';
}
-
bool OurReader::readStringSingleQuote() {
Char c = 0;
while (current_ != end_) {
@@ -1461,19 +1437,21 @@ bool OurReader::readStringSingleQuote() {
return c == '\'';
}
-bool OurReader::readObject(Token& tokenStart) {
+bool OurReader::readObject(Token& token) {
Token tokenName;
- JSONCPP_STRING name;
+ String name;
Value init(objectValue);
currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
+ currentValue().setOffsetStart(token.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
initialTokenOk = readToken(tokenName);
if (!initialTokenOk)
break;
- if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+ if (tokenName.type_ == tokenObjectEnd &&
+ (name.empty() ||
+ features_.allowTrailingCommas_)) // empty object or trailing comma
return true;
name.clear();
if (tokenName.type_ == tokenString) {
@@ -1487,17 +1465,17 @@ bool OurReader::readObject(Token& tokenStart) {
} else {
break;
}
+ if (name.length() >= (1U << 30))
+ throwRuntimeError("keylength >= 2^30");
+ if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+ String msg = "Duplicate key: '" + name + "'";
+ return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
+ }
Token colon;
if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
- return addErrorAndRecover(
- "Missing ':' after object member name", colon, tokenObjectEnd);
- }
- if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
- if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
- JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
- return addErrorAndRecover(
- msg, tokenName, tokenObjectEnd);
+ return addErrorAndRecover("Missing ':' after object member name", colon,
+ tokenObjectEnd);
}
Value& value = currentValue()[name];
nodes_.push(&value);
@@ -1510,8 +1488,8 @@ bool OurReader::readObject(Token& tokenStart) {
if (!readToken(comma) ||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment)) {
- return addErrorAndRecover(
- "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+ return addErrorAndRecover("Missing ',' or '}' in object declaration",
+ comma, tokenObjectEnd);
}
bool finalizeTokenOk = true;
while (comma.type_ == tokenComment && finalizeTokenOk)
@@ -1519,23 +1497,27 @@ bool OurReader::readObject(Token& tokenStart) {
if (comma.type_ == tokenObjectEnd)
return true;
}
- return addErrorAndRecover(
- "Missing '}' or object member name", tokenName, tokenObjectEnd);
+ return addErrorAndRecover("Missing '}' or object member name", tokenName,
+ tokenObjectEnd);
}
-bool OurReader::readArray(Token& tokenStart) {
+bool OurReader::readArray(Token& token) {
Value init(arrayValue);
currentValue().swapPayload(init);
- currentValue().setOffsetStart(tokenStart.start_ - begin_);
- skipSpaces();
- if (current_ != end_ && *current_ == ']') // empty array
- {
- Token endArray;
- readToken(endArray);
- return true;
- }
+ currentValue().setOffsetStart(token.start_ - begin_);
int index = 0;
for (;;) {
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']' &&
+ (index == 0 ||
+ (features_.allowTrailingCommas_ &&
+ !features_.allowDroppedNullPlaceholders_))) // empty array or trailing
+ // comma
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
Value& value = currentValue()[index++];
nodes_.push(&value);
bool ok = readValue();
@@ -1543,19 +1525,19 @@ bool OurReader::readArray(Token& tokenStart) {
if (!ok) // error already set
return recoverFromError(tokenArrayEnd);
- Token token;
+ Token currentToken;
// Accept Comment after last item in the array.
- ok = readToken(token);
- while (token.type_ == tokenComment && ok) {
- ok = readToken(token);
+ ok = readToken(currentToken);
+ while (currentToken.type_ == tokenComment && ok) {
+ ok = readToken(currentToken);
}
- bool badTokenType =
- (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+ bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
+ currentToken.type_ != tokenArrayEnd);
if (!ok || badTokenType) {
- return addErrorAndRecover(
- "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+ return addErrorAndRecover("Missing ',' or ']' in array declaration",
+ currentToken, tokenArrayEnd);
}
- if (token.type_ == tokenArrayEnd)
+ if (currentToken.type_ == tokenArrayEnd)
break;
}
return true;
@@ -1576,38 +1558,78 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
// larger than the maximum supported value of an integer then
// we decode the number as a double.
Location current = token.start_;
- bool isNegative = *current == '-';
- if (isNegative)
+ const bool isNegative = *current == '-';
+ if (isNegative) {
++current;
- // TODO: Help the compiler do the div and mod at compile time or get rid of them.
- Value::LargestUInt maxIntegerValue =
- isNegative ? Value::LargestUInt(Value::minLargestInt)
- : Value::maxLargestUInt;
- Value::LargestUInt threshold = maxIntegerValue / 10;
+ }
+
+ // We assume we can represent the largest and smallest integer types as
+ // unsigned integers with separate sign. This is only true if they can fit
+ // into an unsigned integer.
+ static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
+ "Int must be smaller than UInt");
+
+ // We need to convert minLargestInt into a positive number. The easiest way
+ // to do this conversion is to assume our "threshold" value of minLargestInt
+ // divided by 10 can fit in maxLargestInt when absolute valued. This should
+ // be a safe assumption.
+ static_assert(Value::minLargestInt <= -Value::maxLargestInt,
+ "The absolute value of minLargestInt must be greater than or "
+ "equal to maxLargestInt");
+ static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
+ "The absolute value of minLargestInt must be only 1 magnitude "
+ "larger than maxLargest Int");
+
+ static constexpr Value::LargestUInt positive_threshold =
+ Value::maxLargestUInt / 10;
+ static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
+
+ // For the negative values, we have to be more careful. Since typically
+ // -Value::minLargestInt will cause an overflow, we first divide by 10 and
+ // then take the inverse. This assumes that minLargestInt is only a single
+ // power of 10 different in magnitude, which we check above. For the last
+ // digit, we take the modulus before negating for the same reason.
+ static constexpr auto negative_threshold =
+ Value::LargestUInt(-(Value::minLargestInt / 10));
+ static constexpr auto negative_last_digit =
+ Value::UInt(-(Value::minLargestInt % 10));
+
+ const Value::LargestUInt threshold =
+ isNegative ? negative_threshold : positive_threshold;
+ const Value::UInt max_last_digit =
+ isNegative ? negative_last_digit : positive_last_digit;
+
Value::LargestUInt value = 0;
while (current < token.end_) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
- Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+
+ const auto digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
- // a) we've only just touched the limit, b) this is the last digit, and
+ // a) we've only just touched the limit, meaing value == threshold,
+ // b) this is the last digit, or
// c) it's small enough to fit in that rounding delta, we're okay.
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ ||
- digit > maxIntegerValue % 10) {
+ digit > max_last_digit) {
return decodeDouble(token, decoded);
}
}
value = value * 10 + digit;
}
- if (isNegative)
- decoded = -Value::LargestInt(value);
- else if (value <= Value::LargestUInt(Value::maxInt))
+
+ if (isNegative) {
+ // We use the same magnitude assumption here, just in case.
+ const auto last_digit = static_cast<Value::UInt>(value % 10);
+ decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
+ } else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
decoded = Value::LargestInt(value);
- else
+ } else {
decoded = value;
+ }
+
return true;
}
@@ -1623,44 +1645,18 @@ bool OurReader::decodeDouble(Token& token) {
bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
- const int bufferSize = 32;
- int count;
- ptrdiff_t const length = token.end_ - token.start_;
-
- // Sanity check to avoid buffer overflow exploits.
- if (length < 0) {
- return addError("Unable to parse token length", token);
- }
- size_t const ulength = static_cast<size_t>(length);
-
- // Avoid using a string constant for the format control string given to
- // sscanf, as this can cause hard to debug crashes on OS X. See here for more
- // info:
- //
- // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
- char format[] = "%lf";
-
- if (length <= bufferSize) {
- Char buffer[bufferSize + 1];
- memcpy(buffer, token.start_, ulength);
- buffer[length] = 0;
- fixNumericLocaleInput(buffer, buffer + length);
- count = sscanf(buffer, format, &value);
- } else {
- JSONCPP_STRING buffer(token.start_, token.end_);
- count = sscanf(buffer.c_str(), format, &value);
+ const String buffer(token.start_, token.end_);
+ IStringStream is(buffer);
+ if (!(is >> value)) {
+ return addError(
+ "'" + String(token.start_, token.end_) + "' is not a number.", token);
}
-
- if (count != 1)
- return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
- "' is not a number.",
- token);
decoded = value;
return true;
}
bool OurReader::decodeString(Token& token) {
- JSONCPP_STRING decoded_string;
+ String decoded_string;
if (!decodeString(token, decoded_string))
return false;
Value decoded(decoded_string);
@@ -1670,7 +1666,7 @@ bool OurReader::decodeString(Token& token) {
return true;
}
-bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
+bool OurReader::decodeString(Token& token, String& decoded) {
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
@@ -1678,7 +1674,7 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
Char c = *current++;
if (c == '"')
break;
- else if (c == '\\') {
+ if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@@ -1723,10 +1719,8 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
return true;
}
-bool OurReader::decodeUnicodeCodePoint(Token& token,
- Location& current,
- Location end,
- unsigned int& unicode) {
+bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode) {
unicode = 0; // Convince clang-analyzer that this is initialized before use.
if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
@@ -1736,10 +1730,9 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
if (end - current < 6)
return addError(
"additional six characters expected to parse unicode surrogate pair.",
- token,
- current);
- unsigned int surrogatePair;
+ token, current);
if (*(current++) == '\\' && *(current++) == 'u') {
+ unsigned int surrogatePair;
if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
} else
@@ -1747,20 +1740,17 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
} else
return addError("expecting another \\u token to begin the second half of "
"a unicode surrogate pair",
- token,
- current);
+ token, current);
}
return true;
}
-bool OurReader::decodeUnicodeEscapeSequence(Token& token,
- Location& current,
- Location end,
- unsigned int& ret_unicode) {
+bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
- "Bad unicode escape sequence in string: four digits expected.",
- token,
+ "Bad unicode escape sequence in string: four digits expected.", token,
current);
int unicode = 0;
for (int index = 0; index < 4; ++index) {
@@ -1775,15 +1765,13 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
else
return addError(
"Bad unicode escape sequence in string: hexadecimal digit expected.",
- token,
- current);
+ token, current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
-bool
-OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
+bool OurReader::addError(const String& message, Token& token, Location extra) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
@@ -1805,9 +1793,8 @@ bool OurReader::recoverFromError(TokenType skipUntilToken) {
return false;
}
-bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
- Token& token,
- TokenType skipUntilToken) {
+bool OurReader::addErrorAndRecover(const String& message, Token& token,
+ TokenType skipUntilToken) {
addError(message, token);
return recoverFromError(skipUntilToken);
}
@@ -1820,9 +1807,8 @@ OurReader::Char OurReader::getNextChar() {
return *current_++;
}
-void OurReader::getLocationLineAndColumn(Location location,
- int& line,
- int& column) const {
+void OurReader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const {
Location current = begin_;
Location lastLineStart = current;
line = 0;
@@ -1843,20 +1829,17 @@ void OurReader::getLocationLineAndColumn(Location location,
++line;
}
-JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
+String OurReader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
- snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
return buffer;
}
-JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
- JSONCPP_STRING formattedMessage;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
- const ErrorInfo& error = *itError;
+String OurReader::getFormattedErrorMessages() const {
+ String formattedMessage;
+ for (const auto& error : errors_) {
formattedMessage +=
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
@@ -1869,10 +1852,7 @@ JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
std::vector<OurReader::StructuredError> allErrors;
- for (Errors::const_iterator itError = errors_.begin();
- itError != errors_.end();
- ++itError) {
- const ErrorInfo& error = *itError;
+ for (const auto& error : errors_) {
OurReader::StructuredError structured;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
@@ -1882,59 +1862,15 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
return allErrors;
}
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
- ptrdiff_t length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length)
- return false;
- Token token;
- token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = end_ + value.getOffsetLimit();
- ErrorInfo info;
- info.token_ = token;
- info.message_ = message;
- info.extra_ = 0;
- errors_.push_back(info);
- return true;
-}
-
-bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
- ptrdiff_t length = end_ - begin_;
- if(value.getOffsetStart() > length
- || value.getOffsetLimit() > length
- || extra.getOffsetLimit() > length)
- return false;
- Token token;
- token.type_ = tokenError;
- token.start_ = begin_ + value.getOffsetStart();
- token.end_ = begin_ + value.getOffsetLimit();
- ErrorInfo info;
- info.token_ = token;
- info.message_ = message;
- info.extra_ = begin_ + extra.getOffsetStart();
- errors_.push_back(info);
- return true;
-}
-
-bool OurReader::good() const {
- return !errors_.size();
-}
-
-
class OurCharReader : public CharReader {
bool const collectComments_;
OurReader reader_;
+
public:
- OurCharReader(
- bool collectComments,
- OurFeatures const& features)
- : collectComments_(collectComments)
- , reader_(features)
- {}
- bool parse(
- char const* beginDoc, char const* endDoc,
- Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
+ OurCharReader(bool collectComments, OurFeatures const& features)
+ : collectComments_(collectComments), reader_(features) {}
+ bool parse(char const* beginDoc, char const* endDoc, Value* root,
+ String* errs) override {
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
if (errs) {
*errs = reader_.getFormattedErrorMessages();
@@ -1943,67 +1879,64 @@ public:
}
};
-CharReaderBuilder::CharReaderBuilder()
-{
- setDefaults(&settings_);
-}
-CharReaderBuilder::~CharReaderBuilder()
-{}
-CharReader* CharReaderBuilder::newCharReader() const
-{
+CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
+CharReaderBuilder::~CharReaderBuilder() = default;
+CharReader* CharReaderBuilder::newCharReader() const {
bool collectComments = settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
features.allowComments_ = settings_["allowComments"].asBool();
+ features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
features.strictRoot_ = settings_["strictRoot"].asBool();
- features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+ features.allowDroppedNullPlaceholders_ =
+ settings_["allowDroppedNullPlaceholders"].asBool();
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
- features.stackLimit_ = settings_["stackLimit"].asInt();
+
+ // Stack limit is always a size_t, so we get this as an unsigned int
+ // regardless of it we have 64-bit integer support enabled.
+ features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt());
features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+ features.skipBom_ = settings_["skipBom"].asBool();
return new OurCharReader(collectComments, features);
}
-static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
-{
- valid_keys->clear();
- valid_keys->insert("collectComments");
- valid_keys->insert("allowComments");
- valid_keys->insert("strictRoot");
- valid_keys->insert("allowDroppedNullPlaceholders");
- valid_keys->insert("allowNumericKeys");
- valid_keys->insert("allowSingleQuotes");
- valid_keys->insert("stackLimit");
- valid_keys->insert("failIfExtra");
- valid_keys->insert("rejectDupKeys");
- valid_keys->insert("allowSpecialFloats");
-}
-bool CharReaderBuilder::validate(Json::Value* invalid) const
-{
- Json::Value my_invalid;
- if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
- Json::Value& inv = *invalid;
- std::set<JSONCPP_STRING> valid_keys;
- getValidReaderKeys(&valid_keys);
- Value::Members keys = settings_.getMemberNames();
- size_t n = keys.size();
- for (size_t i = 0; i < n; ++i) {
- JSONCPP_STRING const& key = keys[i];
- if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = settings_[key];
- }
+
+bool CharReaderBuilder::validate(Json::Value* invalid) const {
+ static const auto& valid_keys = *new std::set<String>{
+ "collectComments",
+ "allowComments",
+ "allowTrailingCommas",
+ "strictRoot",
+ "allowDroppedNullPlaceholders",
+ "allowNumericKeys",
+ "allowSingleQuotes",
+ "stackLimit",
+ "failIfExtra",
+ "rejectDupKeys",
+ "allowSpecialFloats",
+ "skipBom",
+ };
+ for (auto si = settings_.begin(); si != settings_.end(); ++si) {
+ auto key = si.name();
+ if (valid_keys.count(key))
+ continue;
+ if (invalid)
+ (*invalid)[std::move(key)] = *si;
+ else
+ return false;
}
- return 0u == inv.size();
+ return invalid ? invalid->empty() : true;
}
-Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
-{
+
+Value& CharReaderBuilder::operator[](const String& key) {
return settings_[key];
}
// static
-void CharReaderBuilder::strictMode(Json::Value* settings)
-{
-//! [CharReaderBuilderStrictMode]
+void CharReaderBuilder::strictMode(Json::Value* settings) {
+ //! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
+ (*settings)["allowTrailingCommas"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@@ -2012,14 +1945,15 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderStrictMode]
+ (*settings)["skipBom"] = true;
+ //! [CharReaderBuilderStrictMode]
}
// static
-void CharReaderBuilder::setDefaults(Json::Value* settings)
-{
-//! [CharReaderBuilderDefaults]
+void CharReaderBuilder::setDefaults(Json::Value* settings) {
+ //! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true;
(*settings)["allowComments"] = true;
+ (*settings)["allowTrailingCommas"] = true;
(*settings)["strictRoot"] = false;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@@ -2028,19 +1962,18 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderDefaults]
+ (*settings)["skipBom"] = true;
+ //! [CharReaderBuilderDefaults]
}
//////////////////////////////////
// global functions
-bool parseFromStream(
- CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
- Value* root, JSONCPP_STRING* errs)
-{
- JSONCPP_OSTRINGSTREAM ssin;
+bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
+ String* errs) {
+ OStringStream ssin;
ssin << sin.rdbuf();
- JSONCPP_STRING doc = ssin.str();
+ String doc = ssin.str();
char const* begin = doc.data();
char const* end = begin + doc.size();
// Note that we do not actually need a null-terminator.
@@ -2048,15 +1981,11 @@ bool parseFromStream(
return reader->parse(begin, end, root, errs);
}
-JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
+IStream& operator>>(IStream& sin, Value& root) {
CharReaderBuilder b;
- JSONCPP_STRING errs;
+ String errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
- fprintf(stderr,
- "Error from reader: %s",
- errs.c_str());
-
throwRuntimeError(errs);
}
return sin;
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_tool.h b/Utilities/cmjsoncpp/src/lib_json/json_tool.h
index 431617830..2d7b7d9a0 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_tool.h
+++ b/Utilities/cmjsoncpp/src/lib_json/json_tool.h
@@ -6,6 +6,9 @@
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/config.h>
+#endif
// Also support old flag NO_LOCALE_SUPPORT
#ifdef NO_LOCALE_SUPPORT
@@ -23,7 +26,7 @@
*/
namespace Json {
-static char getDecimalPoint() {
+static inline char getDecimalPoint() {
#ifdef JSONCPP_NO_LOCALE_SUPPORT
return '\0';
#else
@@ -33,8 +36,8 @@ static char getDecimalPoint() {
}
/// Converts a unicode code-point to UTF-8.
-static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
- JSONCPP_STRING result;
+static inline String codePointToUTF8(unsigned int cp) {
+ String result;
// based on description from http://en.wikipedia.org/wiki/UTF-8
@@ -61,9 +64,6 @@ static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
return result;
}
-/// Returns true if ch is a control character (in range [1,31]).
-static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
-
enum {
/// Constant that specify the size of the buffer that must be passed to
/// uintToString.
@@ -71,10 +71,10 @@ enum {
};
// Defines a char buffer for use with uintToString().
-typedef char UIntToStringBuffer[uintToStringBufferSize];
+using UIntToStringBuffer = char[uintToStringBufferSize];
/** Converts an unsigned integer to string.
- * @param value Unsigned interger to convert to string
+ * @param value Unsigned integer to convert to string
* @param current Input/Output string buffer.
* Must have at least uintToStringBufferSize chars free.
*/
@@ -91,27 +91,44 @@ static inline void uintToString(LargestUInt value, char*& current) {
* We had a sophisticated way, but it did not work in WinCE.
* @see https://github.com/open-source-parsers/jsoncpp/pull/9
*/
-static inline void fixNumericLocale(char* begin, char* end) {
- while (begin < end) {
+template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
+ for (; begin != end; ++begin) {
if (*begin == ',') {
*begin = '.';
}
- ++begin;
}
+ return begin;
}
-static inline void fixNumericLocaleInput(char* begin, char* end) {
+template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
char decimalPoint = getDecimalPoint();
- if (decimalPoint != '\0' && decimalPoint != '.') {
- while (begin < end) {
- if (*begin == '.') {
- *begin = decimalPoint;
- }
- ++begin;
+ if (decimalPoint == '\0' || decimalPoint == '.') {
+ return;
+ }
+ for (; begin != end; ++begin) {
+ if (*begin == '.') {
+ *begin = decimalPoint;
+ }
+ }
+}
+
+/**
+ * Return iterator that would be the new end of the range [begin,end), if we
+ * were to delete zeros in the end of string, but not the last zero before '.'.
+ */
+template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
+ for (; begin != end; --end) {
+ if (*(end - 1) != '0') {
+ return end;
+ }
+ // Don't delete the last zero before the decimal point.
+ if (begin != (end - 1) && *(end - 2) == '.') {
+ return end;
}
}
+ return end;
}
-} // namespace Json {
+} // namespace Json
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
index f271e5731..d59b7d9c9 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp
@@ -8,20 +8,54 @@
#include <json/value.h>
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <math.h>
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
#include <sstream>
#include <utility>
-#include <string.h>
-#include <assert.h>
-#ifdef JSON_USE_CPPTL
-#include <cpptl/conststring.h>
+
+// Provide implementation equivalent of std::snprintf for older _MSC compilers
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#include <stdarg.h>
+static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,
+ const char* format, va_list ap) {
+ int count = -1;
+ if (size != 0)
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ if (count == -1)
+ count = _vscprintf(format, ap);
+ return count;
+}
+
+int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+ const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+ return count;
+}
+#endif
+
+// Disable warning C4702 : unreachable code
+#if defined(_MSC_VER)
+#pragma warning(disable : 4702)
#endif
-#include <cstddef> // size_t
-#include <algorithm> // min()
#define JSON_ASSERT_UNREACHABLE assert(false)
namespace Json {
+template <typename T>
+static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
+ std::unique_ptr<T> r;
+ if (p) {
+ r = std::unique_ptr<T>(new T(*p));
+ }
+ return r;
+}
// This is a walkaround to avoid the static initialization of Value::null.
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
@@ -31,50 +65,34 @@ namespace Json {
#else
#define ALIGNAS(byte_alignment)
#endif
-//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-//const unsigned char& kNullRef = kNull[0];
-//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-//const Value& Value::nullRef = null;
// static
-Value const& Value::nullSingleton()
-{
- static Value const nullStatic;
- return nullStatic;
+Value const& Value::nullSingleton() {
+ static Value const nullStatic;
+ return nullStatic;
}
-// for backwards compatibility, we'll leave these global references around, but DO NOT
-// use them in JSONCPP library code any more!
+#if JSON_USE_NULLREF
+// for backwards compatibility, we'll leave these global references around, but
+// DO NOT use them in JSONCPP library code any more!
+// static
Value const& Value::null = Value::nullSingleton();
-Value const& Value::nullRef = Value::nullSingleton();
-const Int Value::minInt = Int(~(UInt(-1) / 2));
-const Int Value::maxInt = Int(UInt(-1) / 2);
-const UInt Value::maxUInt = UInt(-1);
-#if defined(JSON_HAS_INT64)
-const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
-const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
-const UInt64 Value::maxUInt64 = UInt64(-1);
-// The constant is hard-coded because some compiler have trouble
-// converting Value::maxUInt64 to a double correctly (AIX/xlC).
-// Assumes that UInt64 is a 64 bits integer.
-static const double maxUInt64AsDouble = 18446744073709551615.0;
-#endif // defined(JSON_HAS_INT64)
-const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
-const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
-const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+// static
+Value const& Value::nullRef = Value::nullSingleton();
+#endif
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
// The casts can lose precision, but we are looking only for
// an approximate range. Might fail on edge cases though. ~cdunn
- //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
- return d >= min && d <= max;
+ return d >= static_cast<double>(min) && d <= static_cast<double>(max);
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double integerToDouble(Json::UInt64 value) {
- return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
+ return static_cast<double>(Int64(value / 2)) * 2.0 +
+ static_cast<double>(Int64(value & 1));
}
template <typename T> static inline double integerToDouble(T value) {
@@ -94,19 +112,16 @@ static inline bool InRange(double d, T min, U max) {
* computed using strlen(value).
* @return Pointer on the duplicate instance of string.
*/
-static inline char* duplicateStringValue(const char* value,
- size_t length)
-{
+static inline char* duplicateStringValue(const char* value, size_t length) {
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
if (length >= static_cast<size_t>(Value::maxInt))
length = Value::maxInt - 1;
- char* newString = static_cast<char*>(malloc(length + 1));
- if (newString == NULL) {
- throwRuntimeError(
- "in Json::Value::duplicateStringValue(): "
- "Failed to allocate string value buffer");
+ auto newString = static_cast<char*>(malloc(length + 1));
+ if (newString == nullptr) {
+ throwRuntimeError("in Json::Value::duplicateStringValue(): "
+ "Failed to allocate string value buffer");
}
memcpy(newString, value, length);
newString[length] = 0;
@@ -115,31 +130,28 @@ static inline char* duplicateStringValue(const char* value,
/* Record the length as a prefix.
*/
-static inline char* duplicateAndPrefixStringValue(
- const char* value,
- unsigned int length)
-{
+static inline char* duplicateAndPrefixStringValue(const char* value,
+ unsigned int length) {
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
- JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
+ sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
- unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
- char* newString = static_cast<char*>(malloc(actualLength));
- if (newString == 0) {
- throwRuntimeError(
- "in Json::Value::duplicateAndPrefixStringValue(): "
- "Failed to allocate string value buffer");
+ size_t actualLength = sizeof(length) + length + 1;
+ auto newString = static_cast<char*>(malloc(actualLength));
+ if (newString == nullptr) {
+ throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
+ "Failed to allocate string value buffer");
}
*reinterpret_cast<unsigned*>(newString) = length;
memcpy(newString + sizeof(unsigned), value, length);
- newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+ newString[actualLength - 1U] =
+ 0; // to avoid buffer over-run accidents by users later
return newString;
}
-inline static void decodePrefixedString(
- bool isPrefixed, char const* prefixed,
- unsigned* length, char const** value)
-{
+inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
+ unsigned* length, char const** value) {
if (!isPrefixed) {
*length = static_cast<unsigned>(strlen(prefixed));
*value = prefixed;
@@ -148,7 +160,8 @@ inline static void decodePrefixedString(
*value = prefixed + sizeof(unsigned);
}
}
-/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+/** Free the string duplicated by
+ * duplicateStringValue()/duplicateAndPrefixStringValue().
*/
#if JSONCPP_USING_SECURE_MEMORY
static inline void releasePrefixedStringValue(char* value) {
@@ -161,17 +174,13 @@ static inline void releasePrefixedStringValue(char* value) {
}
static inline void releaseStringValue(char* value, unsigned length) {
// length==0 => we allocated the strings memory
- size_t size = (length==0) ? strlen(value) : length;
+ size_t size = (length == 0) ? strlen(value) : length;
memset(value, 0, size);
free(value);
}
-#else // !JSONCPP_USING_SECURE_MEMORY
-static inline void releasePrefixedStringValue(char* value) {
- free(value);
-}
-static inline void releaseStringValue(char* value, unsigned) {
- free(value);
-}
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) { free(value); }
+static inline void releaseStringValue(char* value, unsigned) { free(value); }
#endif // JSONCPP_USING_SECURE_MEMORY
} // namespace Json
@@ -190,58 +199,28 @@ static inline void releaseStringValue(char* value, unsigned) {
namespace Json {
-Exception::Exception(JSONCPP_STRING const& msg)
- : msg_(msg)
-{}
-Exception::~Exception() JSONCPP_NOEXCEPT
-{}
-char const* Exception::what() const JSONCPP_NOEXCEPT
-{
- return msg_.c_str();
-}
-RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
- : Exception(msg)
-{}
-LogicError::LogicError(JSONCPP_STRING const& msg)
- : Exception(msg)
-{}
-JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
-{
+#if JSON_USE_EXCEPTION
+Exception::Exception(String msg) : msg_(std::move(msg)) {}
+Exception::~Exception() noexcept = default;
+char const* Exception::what() const noexcept { return msg_.c_str(); }
+RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
+LogicError::LogicError(String const& msg) : Exception(msg) {}
+JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
throw RuntimeError(msg);
}
-JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
-{
+JSONCPP_NORETURN void throwLogicError(String const& msg) {
throw LogicError(msg);
}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CommentInfo
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-Value::CommentInfo::CommentInfo() : comment_(0)
-{}
-
-Value::CommentInfo::~CommentInfo() {
- if (comment_)
- releaseStringValue(comment_, 0u);
+#else // !JSON_USE_EXCEPTION
+JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
+ std::cerr << msg << std::endl;
+ abort();
}
-
-void Value::CommentInfo::setComment(const char* text, size_t len) {
- if (comment_) {
- releaseStringValue(comment_, 0u);
- comment_ = 0;
- }
- JSON_ASSERT(text != 0);
- JSON_ASSERT_MESSAGE(
- text[0] == '\0' || text[0] == '/',
- "in Json::Value::setComment(): Comments must start with /");
- // It seems that /**/ style comments are acceptable as well.
- comment_ = duplicateStringValue(text, len);
+JSONCPP_NORETURN void throwLogicError(String const& msg) {
+ std::cerr << msg << std::endl;
+ abort();
}
+#endif
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -254,36 +233,44 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
-Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
-Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+Value::CZString::CZString(char const* str, unsigned length,
+ DuplicationPolicy allocate)
: cstr_(str) {
// allocate != duplicate
storage_.policy_ = allocate & 0x3;
- storage_.length_ = ulength & 0x3FFFFFFF;
+ storage_.length_ = length & 0x3FFFFFFF;
}
Value::CZString::CZString(const CZString& other) {
- cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
- ? duplicateStringValue(other.cstr_, other.storage_.length_)
- : other.cstr_);
- storage_.policy_ = static_cast<unsigned>(other.cstr_
- ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
- ? noDuplication : duplicate)
- : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
+ cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ storage_.policy_ =
+ static_cast<unsigned>(
+ other.cstr_
+ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
+ noDuplication
+ ? noDuplication
+ : duplicate)
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
+ 3U;
storage_.length_ = other.storage_.length_;
}
-#if JSON_HAS_RVALUE_REFERENCES
Value::CZString::CZString(CZString&& other)
- : cstr_(other.cstr_), index_(other.index_) {
+ : cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
}
-#endif
Value::CZString::~CZString() {
if (cstr_ && storage_.policy_ == duplicate) {
- releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
+ releaseStringValue(const_cast<char*>(cstr_),
+ storage_.length_ + 1U); // +1 for null terminating
+ // character for sake of
+ // completeness but not actually
+ // necessary
}
}
@@ -298,36 +285,39 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
return *this;
}
-#if JSON_HAS_RVALUE_REFERENCES
Value::CZString& Value::CZString::operator=(CZString&& other) {
cstr_ = other.cstr_;
index_ = other.index_;
other.cstr_ = nullptr;
return *this;
}
-#endif
bool Value::CZString::operator<(const CZString& other) const {
- if (!cstr_) return index_ < other.index_;
- //return strcmp(cstr_, other.cstr_) < 0;
+ if (!cstr_)
+ return index_ < other.index_;
+ // return strcmp(cstr_, other.cstr_) < 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, min_len);
- if (comp < 0) return true;
- if (comp > 0) return false;
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
return (this_len < other_len);
}
bool Value::CZString::operator==(const CZString& other) const {
- if (!cstr_) return index_ == other.index_;
- //return strcmp(cstr_, other.cstr_) == 0;
+ if (!cstr_)
+ return index_ == other.index_;
+ // return strcmp(cstr_, other.cstr_) == 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
- if (this_len != other_len) return false;
+ if (this_len != other_len)
+ return false;
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, this_len);
return comp == 0;
@@ -335,10 +325,12 @@ bool Value::CZString::operator==(const CZString& other) const {
ArrayIndex Value::CZString::index() const { return index_; }
-//const char* Value::CZString::c_str() const { return cstr_; }
+// const char* Value::CZString::c_str() const { return cstr_; }
const char* Value::CZString::data() const { return cstr_; }
unsigned Value::CZString::length() const { return storage_.length_; }
-bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
+bool Value::CZString::isStaticString() const {
+ return storage_.policy_ == noDuplication;
+}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -352,10 +344,10 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
-Value::Value(ValueType vtype) {
+Value::Value(ValueType type) {
static char const emptyString[] = "";
- initBasic(vtype);
- switch (vtype) {
+ initBasic(type);
+ switch (type) {
case nullValue:
break;
case intValue:
@@ -408,20 +400,22 @@ Value::Value(double value) {
Value::Value(const char* value) {
initBasic(stringValue, true);
- JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
- value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+ JSON_ASSERT_MESSAGE(value != nullptr,
+ "Null Value Passed to Value Constructor");
+ value_.string_ = duplicateAndPrefixStringValue(
+ value, static_cast<unsigned>(strlen(value)));
}
-Value::Value(const char* beginValue, const char* endValue) {
+Value::Value(const char* begin, const char* end) {
initBasic(stringValue, true);
value_.string_ =
- duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+ duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
}
-Value::Value(const JSONCPP_STRING& value) {
+Value::Value(const String& value) {
initBasic(stringValue, true);
- value_.string_ =
- duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+ value_.string_ = duplicateAndPrefixStringValue(
+ value.data(), static_cast<unsigned>(value.length()));
}
Value::Value(const StaticString& value) {
@@ -429,114 +423,44 @@ Value::Value(const StaticString& value) {
value_.string_ = const_cast<char*>(value.c_str());
}
-#ifdef JSON_USE_CPPTL
-Value::Value(const CppTL::ConstString& value) {
- initBasic(stringValue, true);
- value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
-}
-#endif
-
Value::Value(bool value) {
initBasic(booleanValue);
value_.bool_ = value;
}
-Value::Value(Value const& other)
- : type_(other.type_), allocated_(false)
- ,
- comments_(0), start_(other.start_), limit_(other.limit_)
-{
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- value_ = other.value_;
- break;
- case stringValue:
- if (other.value_.string_ && other.allocated_) {
- unsigned len;
- char const* str;
- decodePrefixedString(other.allocated_, other.value_.string_,
- &len, &str);
- value_.string_ = duplicateAndPrefixStringValue(str, len);
- allocated_ = true;
- } else {
- value_.string_ = other.value_.string_;
- allocated_ = false;
- }
- break;
- case arrayValue:
- case objectValue:
- value_.map_ = new ObjectValues(*other.value_.map_);
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
- if (other.comments_) {
- comments_ = new CommentInfo[numberOfCommentPlacement];
- for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
- const CommentInfo& otherComment = other.comments_[comment];
- if (otherComment.comment_)
- comments_[comment].setComment(
- otherComment.comment_, strlen(otherComment.comment_));
- }
- }
+Value::Value(const Value& other) {
+ dupPayload(other);
+ dupMeta(other);
}
-#if JSON_HAS_RVALUE_REFERENCES
-// Move constructor
Value::Value(Value&& other) {
initBasic(nullValue);
swap(other);
}
-#endif
Value::~Value() {
- switch (type_) {
- case nullValue:
- case intValue:
- case uintValue:
- case realValue:
- case booleanValue:
- break;
- case stringValue:
- if (allocated_)
- releasePrefixedStringValue(value_.string_);
- break;
- case arrayValue:
- case objectValue:
- delete value_.map_;
- break;
- default:
- JSON_ASSERT_UNREACHABLE;
- }
-
- delete[] comments_;
-
+ releasePayload();
value_.uint_ = 0;
}
-Value& Value::operator=(Value other) {
- swap(other);
+Value& Value::operator=(const Value& other) {
+ Value(other).swap(*this);
+ return *this;
+}
+
+Value& Value::operator=(Value&& other) {
+ other.swap(*this);
return *this;
}
void Value::swapPayload(Value& other) {
- ValueType temp = type_;
- type_ = other.type_;
- other.type_ = temp;
+ std::swap(bits_, other.bits_);
std::swap(value_, other.value_);
- int temp2 = allocated_;
- allocated_ = other.allocated_;
- other.allocated_ = temp2 & 0x1;
}
void Value::copyPayload(const Value& other) {
- type_ = other.type_;
- value_ = other.value_;
- allocated_ = other.allocated_;
+ releasePayload();
+ dupPayload(other);
}
void Value::swap(Value& other) {
@@ -548,12 +472,12 @@ void Value::swap(Value& other) {
void Value::copy(const Value& other) {
copyPayload(other);
- comments_ = other.comments_;
- start_ = other.start_;
- limit_ = other.limit_;
+ dupMeta(other);
}
-ValueType Value::type() const { return type_; }
+ValueType Value::type() const {
+ return static_cast<ValueType>(bits_.value_type_);
+}
int Value::compare(const Value& other) const {
if (*this < other)
@@ -564,10 +488,10 @@ int Value::compare(const Value& other) const {
}
bool Value::operator<(const Value& other) const {
- int typeDelta = type_ - other.type_;
+ int typeDelta = type() - other.type();
if (typeDelta)
- return typeDelta < 0 ? true : false;
- switch (type_) {
+ return typeDelta < 0;
+ switch (type()) {
case nullValue:
return false;
case intValue:
@@ -578,30 +502,33 @@ bool Value::operator<(const Value& other) const {
return value_.real_ < other.value_.real_;
case booleanValue:
return value_.bool_ < other.value_.bool_;
- case stringValue:
- {
- if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
- if (other.value_.string_) return true;
- else return false;
+ case stringValue: {
+ if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
+ return other.value_.string_ != nullptr;
}
unsigned this_len;
unsigned other_len;
char const* this_str;
char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
+ &other_str);
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, min_len);
- if (comp < 0) return true;
- if (comp > 0) return false;
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
return (this_len < other_len);
}
case arrayValue:
case objectValue: {
- int delta = int(value_.map_->size() - other.value_.map_->size());
- if (delta)
- return delta < 0;
+ auto thisSize = value_.map_->size();
+ auto otherSize = other.value_.map_->size();
+ if (thisSize != otherSize)
+ return thisSize < otherSize;
return (*value_.map_) < (*other.value_.map_);
}
default:
@@ -617,14 +544,9 @@ bool Value::operator>=(const Value& other) const { return !(*this < other); }
bool Value::operator>(const Value& other) const { return other < *this; }
bool Value::operator==(const Value& other) const {
- // if ( type_ != other.type_ )
- // GCC 2.95.3 says:
- // attempt to take address of bit-field structure member `Json::Value::type_'
- // Beats me, but a temp solves the problem.
- int temp = other.type_;
- if (type_ != temp)
+ if (type() != other.type())
return false;
- switch (type_) {
+ switch (type()) {
case nullValue:
return true;
case intValue:
@@ -635,18 +557,20 @@ bool Value::operator==(const Value& other) const {
return value_.real_ == other.value_.real_;
case booleanValue:
return value_.bool_ == other.value_.bool_;
- case stringValue:
- {
- if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+ case stringValue: {
+ if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
return (value_.string_ == other.value_.string_);
}
unsigned this_len;
unsigned other_len;
char const* this_str;
char const* other_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
- if (this_len != other_len) return false;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
+ &other_str);
+ if (this_len != other_len)
+ return false;
JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, this_len);
return comp == 0;
@@ -664,47 +588,55 @@ bool Value::operator==(const Value& other) const {
bool Value::operator!=(const Value& other) const { return !(*this == other); }
const char* Value::asCString() const {
- JSON_ASSERT_MESSAGE(type_ == stringValue,
+ JSON_ASSERT_MESSAGE(type() == stringValue,
"in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0) return 0;
+ if (value_.string_ == nullptr)
+ return nullptr;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
return this_str;
}
#if JSONCPP_USING_SECURE_MEMORY
unsigned Value::getCStringLength() const {
- JSON_ASSERT_MESSAGE(type_ == stringValue,
- "in Json::Value::asCString(): requires stringValue");
- if (value_.string_ == 0) return 0;
+ JSON_ASSERT_MESSAGE(type() == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0)
+ return 0;
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
return this_len;
}
#endif
-bool Value::getString(char const** str, char const** cend) const {
- if (type_ != stringValue) return false;
- if (value_.string_ == 0) return false;
+bool Value::getString(char const** begin, char const** end) const {
+ if (type() != stringValue)
+ return false;
+ if (value_.string_ == nullptr)
+ return false;
unsigned length;
- decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
- *cend = *str + length;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
+ begin);
+ *end = *begin + length;
return true;
}
-JSONCPP_STRING Value::asString() const {
- switch (type_) {
+String Value::asString() const {
+ switch (type()) {
case nullValue:
return "";
- case stringValue:
- {
- if (value_.string_ == 0) return "";
+ case stringValue: {
+ if (value_.string_ == nullptr)
+ return "";
unsigned this_len;
char const* this_str;
- decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
- return JSONCPP_STRING(this_str, this_len);
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ return String(this_str, this_len);
}
case booleanValue:
return value_.bool_ ? "true" : "false";
@@ -719,18 +651,8 @@ JSONCPP_STRING Value::asString() const {
}
}
-#ifdef JSON_USE_CPPTL
-CppTL::ConstString Value::asConstString() const {
- unsigned len;
- char const* str;
- decodePrefixedString(allocated_, value_.string_,
- &len, &str);
- return CppTL::ConstString(str, len);
-}
-#endif
-
Value::Int Value::asInt() const {
- switch (type_) {
+ switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
return Int(value_.int_);
@@ -752,7 +674,7 @@ Value::Int Value::asInt() const {
}
Value::UInt Value::asUInt() const {
- switch (type_) {
+ switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
return UInt(value_.int_);
@@ -776,7 +698,7 @@ Value::UInt Value::asUInt() const {
#if defined(JSON_HAS_INT64)
Value::Int64 Value::asInt64() const {
- switch (type_) {
+ switch (type()) {
case intValue:
return Int64(value_.int_);
case uintValue:
@@ -797,7 +719,7 @@ Value::Int64 Value::asInt64() const {
}
Value::UInt64 Value::asUInt64() const {
- switch (type_) {
+ switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
return UInt64(value_.int_);
@@ -835,7 +757,7 @@ LargestUInt Value::asLargestUInt() const {
}
double Value::asDouble() const {
- switch (type_) {
+ switch (type()) {
case intValue:
return static_cast<double>(value_.int_);
case uintValue:
@@ -857,7 +779,7 @@ double Value::asDouble() const {
}
float Value::asFloat() const {
- switch (type_) {
+ switch (type()) {
case intValue:
return static_cast<float>(value_.int_);
case uintValue:
@@ -872,7 +794,7 @@ float Value::asFloat() const {
case nullValue:
return 0.0;
case booleanValue:
- return value_.bool_ ? 1.0f : 0.0f;
+ return value_.bool_ ? 1.0F : 0.0F;
default:
break;
}
@@ -880,18 +802,20 @@ float Value::asFloat() const {
}
bool Value::asBool() const {
- switch (type_) {
+ switch (type()) {
case booleanValue:
return value_.bool_;
case nullValue:
return false;
case intValue:
- return value_.int_ ? true : false;
+ return value_.int_ != 0;
case uintValue:
- return value_.uint_ ? true : false;
- case realValue:
- // This is kind of strange. Not recommended.
- return (value_.real_ != 0.0) ? true : false;
+ return value_.uint_ != 0;
+ case realValue: {
+ // According to JavaScript language zero or NaN is regarded as false
+ const auto value_classification = std::fpclassify(value_.real_);
+ return value_classification != FP_ZERO && value_classification != FP_NAN;
+ }
default:
break;
}
@@ -902,30 +826,30 @@ bool Value::isConvertibleTo(ValueType other) const {
switch (other) {
case nullValue:
return (isNumeric() && asDouble() == 0.0) ||
- (type_ == booleanValue && value_.bool_ == false) ||
- (type_ == stringValue && asString().empty()) ||
- (type_ == arrayValue && value_.map_->size() == 0) ||
- (type_ == objectValue && value_.map_->size() == 0) ||
- type_ == nullValue;
+ (type() == booleanValue && !value_.bool_) ||
+ (type() == stringValue && asString().empty()) ||
+ (type() == arrayValue && value_.map_->empty()) ||
+ (type() == objectValue && value_.map_->empty()) ||
+ type() == nullValue;
case intValue:
return isInt() ||
- (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
- type_ == booleanValue || type_ == nullValue;
+ (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
+ type() == booleanValue || type() == nullValue;
case uintValue:
return isUInt() ||
- (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
- type_ == booleanValue || type_ == nullValue;
+ (type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
+ type() == booleanValue || type() == nullValue;
case realValue:
- return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ return isNumeric() || type() == booleanValue || type() == nullValue;
case booleanValue:
- return isNumeric() || type_ == booleanValue || type_ == nullValue;
+ return isNumeric() || type() == booleanValue || type() == nullValue;
case stringValue:
- return isNumeric() || type_ == booleanValue || type_ == stringValue ||
- type_ == nullValue;
+ return isNumeric() || type() == booleanValue || type() == stringValue ||
+ type() == nullValue;
case arrayValue:
- return type_ == arrayValue || type_ == nullValue;
+ return type() == arrayValue || type() == nullValue;
case objectValue:
- return type_ == objectValue || type_ == nullValue;
+ return type() == objectValue || type() == nullValue;
}
JSON_ASSERT_UNREACHABLE;
return false;
@@ -933,7 +857,7 @@ bool Value::isConvertibleTo(ValueType other) const {
/// Number of values in array or object
ArrayIndex Value::size() const {
- switch (type_) {
+ switch (type()) {
case nullValue:
case intValue:
case uintValue:
@@ -957,20 +881,19 @@ ArrayIndex Value::size() const {
bool Value::empty() const {
if (isNull() || isArray() || isObject())
- return size() == 0u;
- else
- return false;
+ return size() == 0U;
+ return false;
}
-bool Value::operator!() const { return isNull(); }
+Value::operator bool() const { return !isNull(); }
void Value::clear() {
- JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
- type_ == objectValue,
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
+ type() == objectValue,
"in Json::Value::clear(): requires complex value");
start_ = 0;
limit_ = 0;
- switch (type_) {
+ switch (type()) {
case arrayValue:
case objectValue:
value_.map_->clear();
@@ -981,15 +904,15 @@ void Value::clear() {
}
void Value::resize(ArrayIndex newSize) {
- JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::resize(): requires arrayValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
*this = Value(arrayValue);
ArrayIndex oldSize = size();
if (newSize == 0)
clear();
else if (newSize > oldSize)
- (*this)[newSize - 1];
+ this->operator[](newSize - 1);
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
@@ -1000,12 +923,12 @@ void Value::resize(ArrayIndex newSize) {
Value& Value::operator[](ArrayIndex index) {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
+ type() == nullValue || type() == arrayValue,
"in Json::Value::operator[](ArrayIndex): requires arrayValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
*this = Value(arrayValue);
CZString key(index);
- ObjectValues::iterator it = value_.map_->lower_bound(key);
+ auto it = value_.map_->lower_bound(key);
if (it != value_.map_->end() && (*it).first == key)
return (*it).second;
@@ -1023,9 +946,9 @@ Value& Value::operator[](int index) {
const Value& Value::operator[](ArrayIndex index) const {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == arrayValue,
+ type() == nullValue || type() == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
return nullSingleton();
CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key);
@@ -1041,26 +964,85 @@ const Value& Value::operator[](int index) const {
return (*this)[ArrayIndex(index)];
}
-void Value::initBasic(ValueType vtype, bool allocated) {
- type_ = vtype;
- allocated_ = allocated;
- comments_ = 0;
+void Value::initBasic(ValueType type, bool allocated) {
+ setType(type);
+ setIsAllocated(allocated);
+ comments_ = Comments{};
start_ = 0;
limit_ = 0;
}
+void Value::dupPayload(const Value& other) {
+ setType(other.type());
+ setIsAllocated(false);
+ switch (type()) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_ && other.isAllocated()) {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
+ &str);
+ value_.string_ = duplicateAndPrefixStringValue(str, len);
+ setIsAllocated(true);
+ } else {
+ value_.string_ = other.value_.string_;
+ }
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+void Value::releasePayload() {
+ switch (type()) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (isAllocated())
+ releasePrefixedStringValue(value_.string_);
+ break;
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+void Value::dupMeta(const Value& other) {
+ comments_ = other.comments_;
+ start_ = other.start_;
+ limit_ = other.limit_;
+}
+
// Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null.
// @param key is null-terminated.
Value& Value::resolveReference(const char* key) {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
+ type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(): requires objectValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
*this = Value(objectValue);
- CZString actualKey(
- key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
- ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ CZString actualKey(key, static_cast<unsigned>(strlen(key)),
+ CZString::noDuplication); // NOTE!
+ auto it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
@@ -1071,16 +1053,15 @@ Value& Value::resolveReference(const char* key) {
}
// @param key is not null-terminated.
-Value& Value::resolveReference(char const* key, char const* cend)
-{
+Value& Value::resolveReference(char const* key, char const* end) {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
+ type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(key, end): requires objectValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
*this = Value(objectValue);
- CZString actualKey(
- key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
- ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+ CZString actualKey(key, static_cast<unsigned>(end - key),
+ CZString::duplicateOnCopy);
+ auto it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
@@ -1097,27 +1078,35 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const {
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
-Value const* Value::find(char const* key, char const* cend) const
-{
- JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
- "in Json::Value::find(key, end, found): requires objectValue or nullValue");
- if (type_ == nullValue) return NULL;
- CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+Value const* Value::find(char const* begin, char const* end) const {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::find(begin, end): requires "
+ "objectValue or nullValue");
+ if (type() == nullValue)
+ return nullptr;
+ CZString actualKey(begin, static_cast<unsigned>(end - begin),
+ CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
- if (it == value_.map_->end()) return NULL;
+ if (it == value_.map_->end())
+ return nullptr;
return &(*it).second;
}
-const Value& Value::operator[](const char* key) const
-{
+Value* Value::demand(char const* begin, char const* end) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::demand(begin, end): requires "
+ "objectValue or nullValue");
+ return &resolveReference(begin, end);
+}
+const Value& Value::operator[](const char* key) const {
Value const* found = find(key, key + strlen(key));
- if (!found) return nullSingleton();
+ if (!found)
+ return nullSingleton();
return *found;
}
-Value const& Value::operator[](JSONCPP_STRING const& key) const
-{
+Value const& Value::operator[](const String& key) const {
Value const* found = find(key.data(), key.data() + key.length());
- if (!found) return nullSingleton();
+ if (!found)
+ return nullSingleton();
return *found;
}
@@ -1125,7 +1114,7 @@ Value& Value::operator[](const char* key) {
return resolveReference(key, key + strlen(key));
}
-Value& Value::operator[](const JSONCPP_STRING& key) {
+Value& Value::operator[](const String& key) {
return resolveReference(key.data(), key.data() + key.length());
}
@@ -1133,179 +1122,140 @@ Value& Value::operator[](const StaticString& key) {
return resolveReference(key.c_str());
}
-#ifdef JSON_USE_CPPTL
-Value& Value::operator[](const CppTL::ConstString& key) {
- return resolveReference(key.c_str(), key.end_c_str());
-}
-Value const& Value::operator[](CppTL::ConstString const& key) const
-{
- Value const* found = find(key.c_str(), key.end_c_str());
- if (!found) return nullSingleton();
- return *found;
+Value& Value::append(const Value& value) { return append(Value(value)); }
+
+Value& Value::append(Value&& value) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+ "in Json::Value::append: requires arrayValue");
+ if (type() == nullValue) {
+ *this = Value(arrayValue);
+ }
+ return this->value_.map_->emplace(size(), std::move(value)).first->second;
}
-#endif
-Value& Value::append(const Value& value) { return (*this)[size()] = value; }
+bool Value::insert(ArrayIndex index, const Value& newValue) {
+ return insert(index, Value(newValue));
+}
-#if JSON_HAS_RVALUE_REFERENCES
- Value& Value::append(Value&& value) { return (*this)[size()] = value; }
-#endif
+bool Value::insert(ArrayIndex index, Value&& newValue) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+ "in Json::Value::insert: requires arrayValue");
+ ArrayIndex length = size();
+ if (index > length) {
+ return false;
+ }
+ for (ArrayIndex i = length; i > index; i--) {
+ (*this)[i] = std::move((*this)[i - 1]);
+ }
+ (*this)[index] = std::move(newValue);
+ return true;
+}
-Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
-{
- Value const* found = find(key, cend);
+Value Value::get(char const* begin, char const* end,
+ Value const& defaultValue) const {
+ Value const* found = find(begin, end);
return !found ? defaultValue : *found;
}
-Value Value::get(char const* key, Value const& defaultValue) const
-{
+Value Value::get(char const* key, Value const& defaultValue) const {
return get(key, key + strlen(key), defaultValue);
}
-Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
-{
+Value Value::get(String const& key, Value const& defaultValue) const {
return get(key.data(), key.data() + key.length(), defaultValue);
}
-
-bool Value::removeMember(const char* key, const char* cend, Value* removed)
-{
- if (type_ != objectValue) {
+bool Value::removeMember(const char* begin, const char* end, Value* removed) {
+ if (type() != objectValue) {
return false;
}
- CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
- ObjectValues::iterator it = value_.map_->find(actualKey);
+ CZString actualKey(begin, static_cast<unsigned>(end - begin),
+ CZString::noDuplication);
+ auto it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
- *removed = it->second;
+ if (removed)
+ *removed = std::move(it->second);
value_.map_->erase(it);
return true;
}
-bool Value::removeMember(const char* key, Value* removed)
-{
+bool Value::removeMember(const char* key, Value* removed) {
return removeMember(key, key + strlen(key), removed);
}
-bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
-{
+bool Value::removeMember(String const& key, Value* removed) {
return removeMember(key.data(), key.data() + key.length(), removed);
}
-Value Value::removeMember(const char* key)
-{
- JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+void Value::removeMember(const char* key) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::removeMember(): requires objectValue");
- if (type_ == nullValue)
- return nullSingleton();
+ if (type() == nullValue)
+ return;
- Value removed; // null
- removeMember(key, key + strlen(key), &removed);
- return removed; // still null if removeMember() did nothing
-}
-Value Value::removeMember(const JSONCPP_STRING& key)
-{
- return removeMember(key.c_str());
+ CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
+ value_.map_->erase(actualKey);
}
+void Value::removeMember(const String& key) { removeMember(key.c_str()); }
bool Value::removeIndex(ArrayIndex index, Value* removed) {
- if (type_ != arrayValue) {
+ if (type() != arrayValue) {
return false;
}
CZString key(index);
- ObjectValues::iterator it = value_.map_->find(key);
+ auto it = value_.map_->find(key);
if (it == value_.map_->end()) {
return false;
}
- *removed = it->second;
+ if (removed)
+ *removed = it->second;
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
- for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+ for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
CZString keey(i);
(*value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
- ObjectValues::iterator itLast = value_.map_->find(keyLast);
+ auto itLast = value_.map_->find(keyLast);
value_.map_->erase(itLast);
return true;
}
-#ifdef JSON_USE_CPPTL
-Value Value::get(const CppTL::ConstString& key,
- const Value& defaultValue) const {
- return get(key.c_str(), key.end_c_str(), defaultValue);
+bool Value::isMember(char const* begin, char const* end) const {
+ Value const* value = find(begin, end);
+ return nullptr != value;
}
-#endif
-
-bool Value::isMember(char const* key, char const* cend) const
-{
- Value const* value = find(key, cend);
- return NULL != value;
-}
-bool Value::isMember(char const* key) const
-{
+bool Value::isMember(char const* key) const {
return isMember(key, key + strlen(key));
}
-bool Value::isMember(JSONCPP_STRING const& key) const
-{
+bool Value::isMember(String const& key) const {
return isMember(key.data(), key.data() + key.length());
}
-#ifdef JSON_USE_CPPTL
-bool Value::isMember(const CppTL::ConstString& key) const {
- return isMember(key.c_str(), key.end_c_str());
-}
-#endif
-
Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE(
- type_ == nullValue || type_ == objectValue,
+ type() == nullValue || type() == objectValue,
"in Json::Value::getMemberNames(), value must be objectValue");
- if (type_ == nullValue)
+ if (type() == nullValue)
return Value::Members();
Members members;
members.reserve(value_.map_->size());
ObjectValues::const_iterator it = value_.map_->begin();
ObjectValues::const_iterator itEnd = value_.map_->end();
for (; it != itEnd; ++it) {
- members.push_back(JSONCPP_STRING((*it).first.data(),
- (*it).first.length()));
+ members.push_back(String((*it).first.data(), (*it).first.length()));
}
return members;
}
-//
-//# ifdef JSON_USE_CPPTL
-// EnumMemberNames
-// Value::enumMemberNames() const
-//{
-// if ( type_ == objectValue )
-// {
-// return CppTL::Enum::any( CppTL::Enum::transform(
-// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
-// MemberNamesTransform() ) );
-// }
-// return EnumMemberNames();
-//}
-//
-//
-// EnumValues
-// Value::enumValues() const
-//{
-// if ( type_ == objectValue || type_ == arrayValue )
-// return CppTL::Enum::anyValues( *(value_.map_),
-// CppTL::Type<const Value &>() );
-// return EnumValues();
-//}
-//
-//# endif
static bool IsIntegral(double d) {
double integral_part;
return modf(d, &integral_part) == 0.0;
}
-bool Value::isNull() const { return type_ == nullValue; }
+bool Value::isNull() const { return type() == nullValue; }
-bool Value::isBool() const { return type_ == booleanValue; }
+bool Value::isBool() const { return type() == booleanValue; }
bool Value::isInt() const {
- switch (type_) {
+ switch (type()) {
case intValue:
#if defined(JSON_HAS_INT64)
return value_.int_ >= minInt && value_.int_ <= maxInt;
@@ -1324,7 +1274,7 @@ bool Value::isInt() const {
}
bool Value::isUInt() const {
- switch (type_) {
+ switch (type()) {
case intValue:
#if defined(JSON_HAS_INT64)
return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
@@ -1348,7 +1298,7 @@ bool Value::isUInt() const {
bool Value::isInt64() const {
#if defined(JSON_HAS_INT64)
- switch (type_) {
+ switch (type()) {
case intValue:
return true;
case uintValue:
@@ -1368,7 +1318,7 @@ bool Value::isInt64() const {
bool Value::isUInt64() const {
#if defined(JSON_HAS_INT64)
- switch (type_) {
+ switch (type()) {
case intValue:
return value_.int_ >= 0;
case uintValue:
@@ -1387,61 +1337,92 @@ bool Value::isUInt64() const {
}
bool Value::isIntegral() const {
- switch (type_) {
- case intValue:
- case uintValue:
- return true;
- case realValue:
+ switch (type()) {
+ case intValue:
+ case uintValue:
+ return true;
+ case realValue:
#if defined(JSON_HAS_INT64)
- // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
- // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
- // require the value to be strictly less than the limit.
- return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) &&
+ value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
#else
- return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
+ return value_.real_ >= minInt && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
#endif // JSON_HAS_INT64
- default:
- break;
+ default:
+ break;
}
return false;
}
-bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
+bool Value::isDouble() const {
+ return type() == intValue || type() == uintValue || type() == realValue;
+}
bool Value::isNumeric() const { return isDouble(); }
-bool Value::isString() const { return type_ == stringValue; }
+bool Value::isString() const { return type() == stringValue; }
-bool Value::isArray() const { return type_ == arrayValue; }
+bool Value::isArray() const { return type() == arrayValue; }
-bool Value::isObject() const { return type_ == objectValue; }
+bool Value::isObject() const { return type() == objectValue; }
-void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
- if (!comments_)
- comments_ = new CommentInfo[numberOfCommentPlacement];
- if ((len > 0) && (comment[len-1] == '\n')) {
- // Always discard trailing newline, to aid indentation.
- len -= 1;
- }
- comments_[placement].setComment(comment, len);
+Value::Comments::Comments(const Comments& that)
+ : ptr_{cloneUnique(that.ptr_)} {}
+
+Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
+
+Value::Comments& Value::Comments::operator=(const Comments& that) {
+ ptr_ = cloneUnique(that.ptr_);
+ return *this;
}
-void Value::setComment(const char* comment, CommentPlacement placement) {
- setComment(comment, strlen(comment), placement);
+Value::Comments& Value::Comments::operator=(Comments&& that) {
+ ptr_ = std::move(that.ptr_);
+ return *this;
+}
+
+bool Value::Comments::has(CommentPlacement slot) const {
+ return ptr_ && !(*ptr_)[slot].empty();
}
-void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
- setComment(comment.c_str(), comment.length(), placement);
+String Value::Comments::get(CommentPlacement slot) const {
+ if (!ptr_)
+ return {};
+ return (*ptr_)[slot];
+}
+
+void Value::Comments::set(CommentPlacement slot, String comment) {
+ if (!ptr_) {
+ ptr_ = std::unique_ptr<Array>(new Array());
+ }
+ // check comments array boundry.
+ if (slot < CommentPlacement::numberOfCommentPlacement) {
+ (*ptr_)[slot] = std::move(comment);
+ }
+}
+
+void Value::setComment(String comment, CommentPlacement placement) {
+ if (!comment.empty() && (comment.back() == '\n')) {
+ // Always discard trailing newline, to aid indentation.
+ comment.pop_back();
+ }
+ JSON_ASSERT(!comment.empty());
+ JSON_ASSERT_MESSAGE(
+ comment[0] == '\0' || comment[0] == '/',
+ "in Json::Value::setComment(): Comments must start with /");
+ comments_.set(placement, std::move(comment));
}
bool Value::hasComment(CommentPlacement placement) const {
- return comments_ != 0 && comments_[placement].comment_ != 0;
+ return comments_.has(placement);
}
-JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
- if (hasComment(placement))
- return comments_[placement].comment_;
- return "";
+String Value::getComment(CommentPlacement placement) const {
+ return comments_.get(placement);
}
void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
@@ -1452,18 +1433,18 @@ ptrdiff_t Value::getOffsetStart() const { return start_; }
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
-JSONCPP_STRING Value::toStyledString() const {
+String Value::toStyledString() const {
StreamWriterBuilder builder;
- JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
+ String out = this->hasComment(commentBefore) ? "\n" : "";
out += Json::writeString(builder, *this);
- out += "\n";
+ out += '\n';
return out;
}
Value::const_iterator Value::begin() const {
- switch (type_) {
+ switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
@@ -1472,11 +1453,11 @@ Value::const_iterator Value::begin() const {
default:
break;
}
- return const_iterator();
+ return {};
}
Value::const_iterator Value::end() const {
- switch (type_) {
+ switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
@@ -1485,11 +1466,11 @@ Value::const_iterator Value::end() const {
default:
break;
}
- return const_iterator();
+ return {};
}
Value::iterator Value::begin() {
- switch (type_) {
+ switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
@@ -1502,7 +1483,7 @@ Value::iterator Value::begin() {
}
Value::iterator Value::end() {
- switch (type_) {
+ switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
@@ -1517,25 +1498,20 @@ Value::iterator Value::end() {
// class PathArgument
// //////////////////////////////////////////////////////////////////
-PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+PathArgument::PathArgument() = default;
PathArgument::PathArgument(ArrayIndex index)
- : key_(), index_(index), kind_(kindIndex) {}
+ : index_(index), kind_(kindIndex) {}
-PathArgument::PathArgument(const char* key)
- : key_(key), index_(), kind_(kindKey) {}
+PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
-PathArgument::PathArgument(const JSONCPP_STRING& key)
- : key_(key.c_str()), index_(), kind_(kindKey) {}
+PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
// class Path
// //////////////////////////////////////////////////////////////////
-Path::Path(const JSONCPP_STRING& path,
- const PathArgument& a1,
- const PathArgument& a2,
- const PathArgument& a3,
- const PathArgument& a4,
+Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
+ const PathArgument& a3, const PathArgument& a4,
const PathArgument& a5) {
InArgs in;
in.reserve(5);
@@ -1547,10 +1523,10 @@ Path::Path(const JSONCPP_STRING& path,
makePath(path, in);
}
-void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
+void Path::makePath(const String& path, const InArgs& in) {
const char* current = path.c_str();
const char* end = current + path.length();
- InArgs::const_iterator itInArg = in.begin();
+ auto itInArg = in.begin();
while (current != end) {
if (*current == '[') {
++current;
@@ -1573,13 +1549,12 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
- args_.push_back(JSONCPP_STRING(beginName, current));
+ args_.push_back(String(beginName, current));
}
}
}
-void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
- const InArgs& in,
+void Path::addPathInArg(const String& /*path*/, const InArgs& in,
InArgs::const_iterator& itInArg,
PathArgument::Kind kind) {
if (itInArg == in.end()) {
@@ -1591,30 +1566,29 @@ void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
}
}
-void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
+void Path::invalidPath(const String& /*path*/, int /*location*/) {
// Error: invalid path.
}
const Value& Path::resolve(const Value& root) const {
const Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument& arg = *it;
+ for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
- // Error: unable to resolve path (array value expected at position...
- return Value::null;
+ // Error: unable to resolve path (array value expected at position... )
+ return Value::nullSingleton();
}
node = &((*node)[arg.index_]);
} else if (arg.kind_ == PathArgument::kindKey) {
if (!node->isObject()) {
// Error: unable to resolve path (object value expected at position...)
- return Value::null;
+ return Value::nullSingleton();
}
node = &((*node)[arg.key_]);
if (node == &Value::nullSingleton()) {
// Error: unable to resolve path (object has no member named '' at
// position...)
- return Value::null;
+ return Value::nullSingleton();
}
}
}
@@ -1623,8 +1597,7 @@ const Value& Path::resolve(const Value& root) const {
Value Path::resolve(const Value& root, const Value& defaultValue) const {
const Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument& arg = *it;
+ for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_))
return defaultValue;
@@ -1642,8 +1615,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
Value& Path::make(Value& root) const {
Value* node = &root;
- for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
- const PathArgument& arg = *it;
+ for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray()) {
// Error: node is not an array at position ...
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl b/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl
index 5243bfe4b..d6128b8ed 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl
+++ b/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl
@@ -15,31 +15,21 @@ namespace Json {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-ValueIteratorBase::ValueIteratorBase()
- : current_(), isNull_(true) {
-}
+ValueIteratorBase::ValueIteratorBase() : current_() {}
ValueIteratorBase::ValueIteratorBase(
const Value::ObjectValues::iterator& current)
: current_(current), isNull_(false) {}
-Value& ValueIteratorBase::deref() const {
- return current_->second;
-}
+Value& ValueIteratorBase::deref() { return current_->second; }
+const Value& ValueIteratorBase::deref() const { return current_->second; }
-void ValueIteratorBase::increment() {
- ++current_;
-}
+void ValueIteratorBase::increment() { ++current_; }
-void ValueIteratorBase::decrement() {
- --current_;
-}
+void ValueIteratorBase::decrement() { --current_; }
ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance(const SelfType& other) const {
-#ifdef JSON_USE_CPPTL_SMALLMAP
- return other.current_ - current_;
-#else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance
@@ -60,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
++myDistance;
}
return myDistance;
-#endif
}
bool ValueIteratorBase::isEqual(const SelfType& other) const {
@@ -92,12 +81,13 @@ UInt ValueIteratorBase::index() const {
return Value::UInt(-1);
}
-JSONCPP_STRING ValueIteratorBase::name() const {
+String ValueIteratorBase::name() const {
char const* keey;
char const* end;
keey = memberName(&end);
- if (!keey) return JSONCPP_STRING();
- return JSONCPP_STRING(keey, end);
+ if (!keey)
+ return String();
+ return String(keey, end);
}
char const* ValueIteratorBase::memberName() const {
@@ -108,8 +98,8 @@ char const* ValueIteratorBase::memberName() const {
char const* ValueIteratorBase::memberName(char const** end) const {
const char* cname = (*current_).first.data();
if (!cname) {
- *end = NULL;
- return NULL;
+ *end = nullptr;
+ return nullptr;
}
*end = cname + (*current_).first.length();
return cname;
@@ -123,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-ValueConstIterator::ValueConstIterator() {}
+ValueConstIterator::ValueConstIterator() = default;
ValueConstIterator::ValueConstIterator(
const Value::ObjectValues::iterator& current)
@@ -146,7 +136,7 @@ operator=(const ValueIteratorBase& other) {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
-ValueIterator::ValueIterator() {}
+ValueIterator::ValueIterator() = default;
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
: ValueIteratorBase(current) {}
@@ -156,8 +146,7 @@ ValueIterator::ValueIterator(const ValueConstIterator& other)
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
}
-ValueIterator::ValueIterator(const ValueIterator& other)
- : ValueIteratorBase(other) {}
+ValueIterator::ValueIterator(const ValueIterator& other) = default;
ValueIterator& ValueIterator::operator=(const SelfType& other) {
copy(other);
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
index fc8650598..8bf02dbdb 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@ -4,106 +4,81 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-#include <json/writer.h>
#include "json_tool.h"
+#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstring>
#include <iomanip>
#include <memory>
+#include <set>
#include <sstream>
#include <utility>
-#include <set>
-#include <cassert>
-#include <cstring>
+
+#if __cplusplus >= 201103L
+#include <cmath>
#include <cstdio>
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
-#include <float.h>
-#define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) //Solaris
-#if !defined(isfinite)
-#include <ieeefp.h>
-#define isfinite finite
+#if !defined(isnan)
+#define isnan std::isnan
#endif
-#elif defined(_AIX)
+
#if !defined(isfinite)
-#include <math.h>
-#define isfinite finite
-#endif
-#elif defined(__hpux)
-#if !defined(isfinite) && !defined(__GNUC__)
-#if defined(__ia64) && !defined(finite)
-#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _IsFinite(x)))
-#else
-#include <math.h>
-#define isfinite finite
-#endif
+#define isfinite std::isfinite
#endif
+
#else
#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
-#endif
+#include <cstdio>
#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
+#if !defined(isnan)
+#include <float.h>
+#define isnan _isnan
#endif
-#if defined(__BORLANDC__)
+#if !defined(isfinite)
#include <float.h>
#define isfinite _finite
-#define snprintf _snprintf
#endif
-// Solaris
-#if defined(__sun)
-# include <ieeefp.h>
-# if !defined(isfinite)
-# define isfinite finite
-# endif
-#endif
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+
+#endif //_MSC_VER
-// AIX
-#if defined(_AIX)
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+#if defined(__sun) && defined(__SVR4) // Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
#endif
-// HP-UX
#if defined(__hpux)
-# if !defined(isfinite)
-# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
-# define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _Isfinite(x)))
-# else
-# include <math.h>
-# define isfinite finite
-# endif
-# endif
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) \
+ ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
+#endif
+#endif
+#endif
+
+#if !defined(isnan)
+// IEEE standard states that NaN values will not compare to themselves
+#define isnan(x) (x != x)
#endif
-// Ancient glibc
-#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
-# if !defined(isfinite)
-# define isfinite __finite
-# endif
+#if !defined(__APPLE__)
+#if !defined(isfinite)
+#define isfinite finite
+#endif
+#endif
#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+#if defined(_MSC_VER)
// Disable warning about strdup being deprecated.
#pragma warning(disable : 4996)
#endif
@@ -111,30 +86,12 @@
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::auto_ptr<StreamWriter>;
#endif
-static bool containsControlCharacter(const char* str) {
- while (*str) {
- if (isControlCharacter(*(str++)))
- return true;
- }
- return false;
-}
-
-static bool containsControlCharacter0(const char* str, unsigned len) {
- char const* end = str + len;
- while (end != str) {
- if (isControlCharacter(*str) || 0==*str)
- return true;
- ++str;
- }
- return false;
-}
-
-JSONCPP_STRING valueToString(LargestInt value) {
+String valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
if (value == Value::minLargestInt) {
@@ -150,7 +107,7 @@ JSONCPP_STRING valueToString(LargestInt value) {
return current;
}
-JSONCPP_STRING valueToString(LargestUInt value) {
+String valueToString(LargestUInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -160,147 +117,171 @@ JSONCPP_STRING valueToString(LargestUInt value) {
#if defined(JSON_HAS_INT64)
-JSONCPP_STRING valueToString(Int value) {
- return valueToString(LargestInt(value));
-}
+String valueToString(Int value) { return valueToString(LargestInt(value)); }
-JSONCPP_STRING valueToString(UInt value) {
- return valueToString(LargestUInt(value));
-}
+String valueToString(UInt value) { return valueToString(LargestUInt(value)); }
#endif // # if defined(JSON_HAS_INT64)
namespace {
-JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
- // Allocate a buffer that is more than large enough to store the 16 digits of
- // precision requested below.
- char buffer[36];
- int len = -1;
-
- char formatString[15];
- snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
-
+String valueToString(double value, bool useSpecialFloats,
+ unsigned int precision, PrecisionType precisionType) {
// Print into the buffer. We need not request the alternative representation
- // that always has a decimal point because JSON doesn't distingish the
+ // that always has a decimal point because JSON doesn't distinguish the
// concepts of reals and integers.
- if (isfinite(value)) {
- len = snprintf(buffer, sizeof(buffer), formatString, value);
- fixNumericLocale(buffer, buffer + len);
+ if (!isfinite(value)) {
+ static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
+ {"null", "-1e+9999", "1e+9999"}};
+ return reps[useSpecialFloats ? 0 : 1]
+ [isnan(value) ? 0 : (value < 0) ? 1 : 2];
+ }
- // try to ensure we preserve the fact that this was given to us as a double on input
- if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
- strcat(buffer, ".0");
+ String buffer(size_t(36), '\0');
+ while (true) {
+ int len = jsoncpp_snprintf(
+ &*buffer.begin(), buffer.size(),
+ (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
+ precision, value);
+ assert(len >= 0);
+ auto wouldPrint = static_cast<size_t>(len);
+ if (wouldPrint >= buffer.size()) {
+ buffer.resize(wouldPrint + 1);
+ continue;
}
+ buffer.resize(wouldPrint);
+ break;
+ }
- } else {
- // IEEE standard states that NaN values will not compare to themselves
- if (value != value) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
- } else if (value < 0) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
- } else {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
- }
+ buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
+
+ // strip the zero padding from the right
+ if (precisionType == PrecisionType::decimalPlaces) {
+ buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
+ }
+
+ // try to ensure we preserve the fact that this was given to us as a double on
+ // input
+ if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
+ buffer += ".0";
}
- assert(len >= 0);
return buffer;
}
+} // namespace
+
+String valueToString(double value, unsigned int precision,
+ PrecisionType precisionType) {
+ return valueToString(value, false, precision, precisionType);
}
-JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
+String valueToString(bool value) { return value ? "true" : "false"; }
-JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
+static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
+ assert(s || !n);
-JSONCPP_STRING valueToQuotedString(const char* value) {
- if (value == NULL)
- return "";
- // Not sure how to handle unicode...
- if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
- !containsControlCharacter(value))
- return JSONCPP_STRING("\"") + value + "\"";
- // We have to walk value and escape any special characters.
- // Appending to JSONCPP_STRING is not efficient, but this should be rare.
- // (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- strlen(value) * 2 + 3; // allescaped+quotes+NULL
- JSONCPP_STRING result;
- result.reserve(maxsize); // to avoid lots of mallocs
- result += "\"";
- for (const char* c = value; *c != 0; ++c) {
- switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
- }
+ return std::any_of(s, s + n, [](unsigned char c) {
+ return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
+ });
+}
+
+static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
+ const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
+
+ unsigned int firstByte = static_cast<unsigned char>(*s);
+
+ if (firstByte < 0x80)
+ return firstByte;
+
+ if (firstByte < 0xE0) {
+ if (e - s < 2)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated =
+ ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
+ s += 1;
+ // oversized encoded characters are invalid
+ return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
}
- result += "\"";
+
+ if (firstByte < 0xF0) {
+ if (e - s < 3)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x0F) << 12) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[2]) & 0x3F);
+ s += 2;
+ // surrogates aren't valid codepoints itself
+ // shouldn't be UTF-8 encoded
+ if (calculated >= 0xD800 && calculated <= 0xDFFF)
+ return REPLACEMENT_CHARACTER;
+ // oversized encoded characters are invalid
+ return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ if (firstByte < 0xF8) {
+ if (e - s < 4)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x07) << 18) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
+ ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[3]) & 0x3F);
+ s += 3;
+ // oversized encoded characters are invalid
+ return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ return REPLACEMENT_CHARACTER;
+}
+
+static const char hex2[] = "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+static String toHex16Bit(unsigned int x) {
+ const unsigned int hi = (x >> 8) & 0xff;
+ const unsigned int lo = x & 0xff;
+ String result(4, ' ');
+ result[0] = hex2[2 * hi];
+ result[1] = hex2[2 * hi + 1];
+ result[2] = hex2[2 * lo];
+ result[3] = hex2[2 * lo + 1];
return result;
}
-// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n) {
- assert((s || !n) && accept);
+static void appendRaw(String& result, unsigned ch) {
+ result += static_cast<char>(ch);
+}
- char const* const end = s + n;
- for (char const* cur = s; cur < end; ++cur) {
- int const c = *cur;
- for (char const* a = accept; *a; ++a) {
- if (*a == c) {
- return cur;
- }
- }
- }
- return NULL;
+static void appendHex(String& result, unsigned ch) {
+ result.append("\\u").append(toHex16Bit(ch));
}
-static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
- if (value == NULL)
+
+static String valueToQuotedStringN(const char* value, unsigned length,
+ bool emitUTF8 = false) {
+ if (value == nullptr)
return "";
- // Not sure how to handle unicode...
- if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
- !containsControlCharacter0(value, length))
- return JSONCPP_STRING("\"") + value + "\"";
+
+ if (!doesAnyCharRequireEscaping(value, length))
+ return String("\"") + value + "\"";
// We have to walk value and escape any special characters.
- // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+ // Appending to String is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- length * 2 + 3; // allescaped+quotes+NULL
- JSONCPP_STRING result;
+ String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
+ String result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
char const* end = value + length;
@@ -335,44 +316,63 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
// sequence.
// Should add a flag to allow this compatibility mode and prevent this
// sequence from occurring.
- default:
- if ((isControlCharacter(*c)) || (*c == 0)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
+ default: {
+ if (emitUTF8) {
+ unsigned codepoint = static_cast<unsigned char>(*c);
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else {
+ appendRaw(result, codepoint);
+ }
} else {
- result += *c;
+ unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else if (codepoint < 0x80) {
+ appendRaw(result, codepoint);
+ } else if (codepoint < 0x10000) {
+ // Basic Multilingual Plane
+ appendHex(result, codepoint);
+ } else {
+ // Extended Unicode. Encode 20 bits as a surrogate pair.
+ codepoint -= 0x10000;
+ appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
+ appendHex(result, 0xdc00 + (codepoint & 0x3ff));
+ }
}
- break;
+ } break;
}
}
result += "\"";
return result;
}
+String valueToQuotedString(const char* value) {
+ return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
+}
+
// Class Writer
// //////////////////////////////////////////////////////////////////
-Writer::~Writer() {}
+Writer::~Writer() = default;
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
- omitEndingLineFeed_(false) {}
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+ = default;
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
-JSONCPP_STRING FastWriter::write(const Value& root) {
+String FastWriter::write(const Value& root) {
document_.clear();
writeValue(root);
if (!omitEndingLineFeed_)
- document_ += "\n";
+ document_ += '\n';
return document_;
}
@@ -391,13 +391,13 @@ void FastWriter::writeValue(const Value& value) {
case realValue:
document_ += valueToString(value.asDouble());
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+ if (ok)
+ document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
break;
}
case booleanValue:
@@ -416,13 +416,13 @@ void FastWriter::writeValue(const Value& value) {
case objectValue: {
Value::Members members(value.getMemberNames());
document_ += '{';
- for (Value::Members::iterator it = members.begin(); it != members.end();
- ++it) {
- const JSONCPP_STRING& name = *it;
+ for (auto it = members.begin(); it != members.end(); ++it) {
+ const String& name = *it;
if (it != members.begin())
document_ += ',';
- document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ document_ += valueToQuotedStringN(name.data(),
+ static_cast<unsigned>(name.length()));
+ document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
document_ += '}';
@@ -433,17 +433,16 @@ void FastWriter::writeValue(const Value& value) {
// Class StyledWriter
// //////////////////////////////////////////////////////////////////
-StyledWriter::StyledWriter()
- : rightMargin_(74), indentSize_(3), addChildValues_() {}
+StyledWriter::StyledWriter() = default;
-JSONCPP_STRING StyledWriter::write(const Value& root) {
+String StyledWriter::write(const Value& root) {
document_.clear();
addChildValues_ = false;
indentString_.clear();
writeCommentBeforeValue(root);
writeValue(root);
writeCommentAfterValueOnSameLine(root);
- document_ += "\n";
+ document_ += '\n';
return document_;
}
@@ -461,14 +460,15 @@ void StyledWriter::writeValue(const Value& value) {
case realValue:
pushValue(valueToString(value.asDouble()));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -484,9 +484,9 @@ void StyledWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- const JSONCPP_STRING& name = *it;
+ const String& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -511,7 +511,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -549,14 +549,14 @@ void StyledWriter::writeArrayValue(const Value& value) {
}
}
-bool StyledWriter::isMultineArray(const Value& value) {
+bool StyledWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -576,7 +576,7 @@ bool StyledWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledWriter::pushValue(const JSONCPP_STRING& value) {
+void StyledWriter::pushValue(const String& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -594,12 +594,12 @@ void StyledWriter::writeIndent() {
document_ += indentString_;
}
-void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
+void StyledWriter::writeWithIndent(const String& value) {
writeIndent();
document_ += value;
}
-void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); }
void StyledWriter::unindent() {
assert(indentString_.size() >= indentSize_);
@@ -610,20 +610,19 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- document_ += "\n";
+ document_ += '\n';
writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
document_ += *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
writeIndent();
++iter;
}
// Comments are stripped of trailing newlines, so add one here
- document_ += "\n";
+ document_ += '\n';
}
void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
@@ -631,9 +630,9 @@ void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
document_ += " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- document_ += "\n";
+ document_ += '\n';
document_ += root.getComment(commentAfter);
- document_ += "\n";
+ document_ += '\n';
}
}
@@ -646,22 +645,23 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
-StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
- : document_(NULL), rightMargin_(74), indentation_(indentation),
- addChildValues_() {}
+StyledStreamWriter::StyledStreamWriter(String indentation)
+ : document_(nullptr), indentation_(std::move(indentation)),
+ addChildValues_(), indented_(false) {}
-void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
+void StyledStreamWriter::write(OStream& out, const Value& root) {
document_ = &out;
addChildValues_ = false;
indentString_.clear();
indented_ = true;
writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*document_ << "\n";
- document_ = NULL; // Forget the stream, for safety.
+ document_ = nullptr; // Forget the stream, for safety.
}
void StyledStreamWriter::writeValue(const Value& value) {
@@ -678,14 +678,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
case realValue:
pushValue(valueToString(value.asDouble()));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -701,9 +702,9 @@ void StyledStreamWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- const JSONCPP_STRING& name = *it;
+ const String& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -728,7 +729,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -740,7 +741,8 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (hasChildValue)
writeWithIndent(childValues_[index]);
else {
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(childValue);
indented_ = false;
@@ -768,14 +770,14 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value) {
+bool StyledStreamWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -795,7 +797,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
+void StyledStreamWriter::pushValue(const String& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -810,8 +812,9 @@ void StyledStreamWriter::writeIndent() {
*document_ << '\n' << indentString_;
}
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
- if (!indented_) writeIndent();
+void StyledStreamWriter::writeWithIndent(const String& value) {
+ if (!indented_)
+ writeIndent();
*document_ << value;
indented_ = false;
}
@@ -827,13 +830,13 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*document_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would include newline
*document_ << indentString_;
++iter;
@@ -865,84 +868,73 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
struct CommentStyle {
/// Decide whether to write comments.
enum Enum {
- None, ///< Drop all comments.
- Most, ///< Recover odd behavior of previous versions (not implemented yet).
- All ///< Keep all comments.
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
};
};
-struct BuiltStyledStreamWriter : public StreamWriter
-{
- BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision);
- int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
+struct BuiltStyledStreamWriter : public StreamWriter {
+ BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs,
+ String colonSymbol, String nullSymbol,
+ String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision,
+ PrecisionType precisionType);
+ int write(Value const& root, OStream* sout) override;
+
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
- bool isMultineArray(Value const& value);
- void pushValue(JSONCPP_STRING const& value);
+ bool isMultilineArray(Value const& value);
+ void pushValue(String const& value);
void writeIndent();
- void writeWithIndent(JSONCPP_STRING const& value);
+ void writeWithIndent(String const& value);
void indent();
void unindent();
void writeCommentBeforeValue(Value const& root);
void writeCommentAfterValueOnSameLine(Value const& root);
static bool hasCommentForValue(const Value& value);
- typedef std::vector<JSONCPP_STRING> ChildValues;
+ using ChildValues = std::vector<String>;
ChildValues childValues_;
- JSONCPP_STRING indentString_;
+ String indentString_;
unsigned int rightMargin_;
- JSONCPP_STRING indentation_;
+ String indentation_;
CommentStyle::Enum cs_;
- JSONCPP_STRING colonSymbol_;
- JSONCPP_STRING nullSymbol_;
- JSONCPP_STRING endingLineFeedSymbol_;
+ String colonSymbol_;
+ String nullSymbol_;
+ String endingLineFeedSymbol_;
bool addChildValues_ : 1;
bool indented_ : 1;
bool useSpecialFloats_ : 1;
+ bool emitUTF8_ : 1;
unsigned int precision_;
+ PrecisionType precisionType_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision)
- : rightMargin_(74)
- , indentation_(indentation)
- , cs_(cs)
- , colonSymbol_(colonSymbol)
- , nullSymbol_(nullSymbol)
- , endingLineFeedSymbol_(endingLineFeedSymbol)
- , addChildValues_(false)
- , indented_(false)
- , useSpecialFloats_(useSpecialFloats)
- , precision_(precision)
-{
-}
-int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
-{
+ String indentation, CommentStyle::Enum cs, String colonSymbol,
+ String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision, PrecisionType precisionType)
+ : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
+ colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
+ endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
+ addChildValues_(false), indented_(false),
+ useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
+ precision_(precision), precisionType_(precisionType) {}
+int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
sout_ = sout;
addChildValues_ = false;
indented_ = true;
indentString_.clear();
writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*sout_ << endingLineFeedSymbol_;
- sout_ = NULL;
+ sout_ = nullptr;
return 0;
}
void BuiltStyledStreamWriter::writeValue(Value const& value) {
@@ -957,16 +949,19 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
pushValue(valueToString(value.asLargestUInt()));
break;
case realValue:
- pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_,
+ precisionType_));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL is possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
+ emitUTF8_));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -982,12 +977,13 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- JSONCPP_STRING const& name = *it;
+ String const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+ writeWithIndent(valueToQuotedStringN(
+ name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -1009,7 +1005,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (size == 0)
pushValue("[]");
else {
- bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
if (isMultiLine) {
writeWithIndent("[");
indent();
@@ -1021,7 +1017,8 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (hasChildValue)
writeWithIndent(childValues_[index]);
else {
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(childValue);
indented_ = false;
@@ -1039,26 +1036,28 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
{
assert(childValues_.size() == size);
*sout_ << "[";
- if (!indentation_.empty()) *sout_ << " ";
+ if (!indentation_.empty())
+ *sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
*sout_ << ((!indentation_.empty()) ? ", " : ",");
*sout_ << childValues_[index];
}
- if (!indentation_.empty()) *sout_ << " ";
+ if (!indentation_.empty())
+ *sout_ << " ";
*sout_ << "]";
}
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -1078,7 +1077,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
+void BuiltStyledStreamWriter::pushValue(String const& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -1097,8 +1096,9 @@ void BuiltStyledStreamWriter::writeIndent() {
}
}
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
- if (!indented_) writeIndent();
+void BuiltStyledStreamWriter::writeWithIndent(String const& value) {
+ if (!indented_)
+ writeIndent();
*sout_ << value;
indented_ = false;
}
@@ -1111,17 +1111,18 @@ void BuiltStyledStreamWriter::unindent() {
}
void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+ if (cs_ == CommentStyle::None)
+ return;
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*sout_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would write extra newline
*sout_ << indentString_;
++iter;
@@ -1129,8 +1130,10 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
indented_ = false;
}
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
+ Value const& root) {
+ if (cs_ == CommentStyle::None)
+ return;
if (root.hasComment(commentAfterOnSameLine))
*sout_ << " " + root.getComment(commentAfterOnSameLine);
@@ -1150,28 +1153,19 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
///////////////
// StreamWriter
-StreamWriter::StreamWriter()
- : sout_(NULL)
-{
-}
-StreamWriter::~StreamWriter()
-{
-}
-StreamWriter::Factory::~Factory()
-{}
-StreamWriterBuilder::StreamWriterBuilder()
-{
- setDefaults(&settings_);
-}
-StreamWriterBuilder::~StreamWriterBuilder()
-{}
-StreamWriter* StreamWriterBuilder::newStreamWriter() const
-{
- JSONCPP_STRING indentation = settings_["indentation"].asString();
- JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
- bool eyc = settings_["enableYAMLCompatibility"].asBool();
- bool dnp = settings_["dropNullPlaceholders"].asBool();
- bool usf = settings_["useSpecialFloats"].asBool();
+StreamWriter::StreamWriter() : sout_(nullptr) {}
+StreamWriter::~StreamWriter() = default;
+StreamWriter::Factory::~Factory() = default;
+StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
+StreamWriterBuilder::~StreamWriterBuilder() = default;
+StreamWriter* StreamWriterBuilder::newStreamWriter() const {
+ const String indentation = settings_["indentation"].asString();
+ const String cs_str = settings_["commentStyle"].asString();
+ const String pt_str = settings_["precisionType"].asString();
+ const bool eyc = settings_["enableYAMLCompatibility"].asBool();
+ const bool dnp = settings_["dropNullPlaceholders"].asBool();
+ const bool usf = settings_["useSpecialFloats"].asBool();
+ const bool emitUTF8 = settings_["emitUTF8"].asBool();
unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
@@ -1181,74 +1175,80 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
} else {
throwRuntimeError("commentStyle must be 'All' or 'None'");
}
- JSONCPP_STRING colonSymbol = " : ";
+ PrecisionType precisionType(significantDigits);
+ if (pt_str == "significant") {
+ precisionType = PrecisionType::significantDigits;
+ } else if (pt_str == "decimal") {
+ precisionType = PrecisionType::decimalPlaces;
+ } else {
+ throwRuntimeError("precisionType must be 'significant' or 'decimal'");
+ }
+ String colonSymbol = " : ";
if (eyc) {
colonSymbol = ": ";
} else if (indentation.empty()) {
colonSymbol = ":";
}
- JSONCPP_STRING nullSymbol = "null";
+ String nullSymbol = "null";
if (dnp) {
nullSymbol.clear();
}
- if (pre > 17) pre = 17;
- JSONCPP_STRING endingLineFeedSymbol;
- return new BuiltStyledStreamWriter(
- indentation, cs,
- colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+ if (pre > 17)
+ pre = 17;
+ String endingLineFeedSymbol;
+ return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
+ endingLineFeedSymbol, usf, emitUTF8, pre,
+ precisionType);
}
-static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
-{
- valid_keys->clear();
- valid_keys->insert("indentation");
- valid_keys->insert("commentStyle");
- valid_keys->insert("enableYAMLCompatibility");
- valid_keys->insert("dropNullPlaceholders");
- valid_keys->insert("useSpecialFloats");
- valid_keys->insert("precision");
-}
-bool StreamWriterBuilder::validate(Json::Value* invalid) const
-{
- Json::Value my_invalid;
- if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
- Json::Value& inv = *invalid;
- std::set<JSONCPP_STRING> valid_keys;
- getValidWriterKeys(&valid_keys);
- Value::Members keys = settings_.getMemberNames();
- size_t n = keys.size();
- for (size_t i = 0; i < n; ++i) {
- JSONCPP_STRING const& key = keys[i];
- if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = settings_[key];
- }
+
+bool StreamWriterBuilder::validate(Json::Value* invalid) const {
+ static const auto& valid_keys = *new std::set<String>{
+ "indentation",
+ "commentStyle",
+ "enableYAMLCompatibility",
+ "dropNullPlaceholders",
+ "useSpecialFloats",
+ "emitUTF8",
+ "precision",
+ "precisionType",
+ };
+ for (auto si = settings_.begin(); si != settings_.end(); ++si) {
+ auto key = si.name();
+ if (valid_keys.count(key))
+ continue;
+ if (invalid)
+ (*invalid)[std::move(key)] = *si;
+ else
+ return false;
}
- return 0u == inv.size();
+ return invalid ? invalid->empty() : true;
}
-Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
-{
+
+Value& StreamWriterBuilder::operator[](const String& key) {
return settings_[key];
}
// static
-void StreamWriterBuilder::setDefaults(Json::Value* settings)
-{
+void StreamWriterBuilder::setDefaults(Json::Value* settings) {
//! [StreamWriterBuilderDefaults]
(*settings)["commentStyle"] = "All";
(*settings)["indentation"] = "\t";
(*settings)["enableYAMLCompatibility"] = false;
(*settings)["dropNullPlaceholders"] = false;
(*settings)["useSpecialFloats"] = false;
+ (*settings)["emitUTF8"] = false;
(*settings)["precision"] = 17;
+ (*settings)["precisionType"] = "significant";
//! [StreamWriterBuilderDefaults]
}
-JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
- JSONCPP_OSTRINGSTREAM sout;
- StreamWriterPtr const writer(builder.newStreamWriter());
+String writeString(StreamWriter::Factory const& factory, Value const& root) {
+ OStringStream sout;
+ StreamWriterPtr const writer(factory.newStreamWriter());
writer->write(root, &sout);
return sout.str();
}
-JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
+OStream& operator<<(OStream& sout, Value const& root) {
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt
index 79452ffff..ba6547096 100644
--- a/Utilities/cmlibarchive/CMakeLists.txt
+++ b/Utilities/cmlibarchive/CMakeLists.txt
@@ -171,32 +171,32 @@ IF (MSVC)
# This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug"
# Enable level 4 C4062: The enumerate has no associated handler in a switch
# statement and there is no default that can catch it.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4062")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14062")
# Enable level 4 C4254: A larger bit field was assigned to a smaller bit
# field.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14254")
# Enable level 4 C4295: An array was initialized but the last character in
# the array is not a null; accessing the array may
# produce unexpected results.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4295")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14295")
# Enable level 4 C4296: An unsigned variable was used in a comparison
# operation with zero.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4296")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14296")
# Enable level 4 C4389: An operation involved signed and unsigned variables.
# This could result in a loss of data.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4389")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14389")
# Enable level 4 C4505: The given function is local and not referenced in
# the body of the module; therefore, the function is
# dead code.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4505")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14505")
# Enable level 4 C4514: The optimizer removed an inline function that is not
# called.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4514")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14514")
# Enable level 4 C4702: Unreachable code.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4702")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14702")
# Enable level 4 C4706: The test value in a conditional expression was the
# result of an assignment.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4706")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /w14706")
# /Oi option enables built-in functions.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Oi")
#################################################################
@@ -1404,6 +1404,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR)
CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP)
CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR)
CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S)
+CHECK_FUNCTION_EXISTS_GLIBC(strnlen HAVE_STRNLEN)
CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR)
CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK)
CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM)
@@ -1475,15 +1476,19 @@ CHECK_C_SOURCE_COMPILES(
"#include <sys/sysmacros.h>\nint main() { return major(256); }"
MAJOR_IN_SYSMACROS)
+IF(ENABLE_LZMA)
CMAKE_PUSH_CHECK_STATE()
SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES})
SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR})
CHECK_C_SOURCE_COMPILES(
"#include <lzma.h>\n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}"
-HAVE_LZMA_STREAM_ENCODER_MT)
+ HAVE_LZMA_STREAM_ENCODER_MT)
CMAKE_POP_CHECK_STATE()
+ELSE()
+ SET(HAVE_LZMA_STREAM_ENCODER_MT 0)
+ENDIF(ENABLE_LZMA)
IF(HAVE_STRERROR_R)
SET(HAVE_DECL_STRERROR_R 1)
@@ -2007,6 +2012,11 @@ IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ENDIF(MSVC)
+IF(APPLE)
+ # CC_MD5_Init() functions are deprecated on macOS 10.15, but we want to use them
+ ADD_DEFINITIONS(-Wno-deprecated-declarations)
+ENDIF(APPLE)
+
IF(0) # CMake does not build libarchive's tests.
IF(ENABLE_TEST)
ADD_CUSTOM_TARGET(run_all_tests)
diff --git a/Utilities/cmlibarchive/COPYING b/Utilities/cmlibarchive/COPYING
index 14bbefa0d..1b9723574 100644
--- a/Utilities/cmlibarchive/COPYING
+++ b/Utilities/cmlibarchive/COPYING
@@ -15,7 +15,6 @@ the actual statements in the files are controlling.
* The following source files are also subject in whole or in part to
a 3-clause UC Regents copyright; please read the individual source
files for details:
- libarchive/archive_entry.c
libarchive/archive_read_support_filter_compress.c
libarchive/archive_write_add_filter_compress.c
libarchive/mtree.5
diff --git a/Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake b/Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake
index fc8529a57..bc5a43f72 100644
--- a/Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake
+++ b/Utilities/cmlibarchive/build/cmake/CreatePkgConfigFile.cmake
@@ -24,10 +24,10 @@ ENDFOREACH()
# thus there's a good chance it'll make some binutils versions unhappy...
# This only affects Libs.private (looked up for static builds) though.
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in
- ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
+ ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
@ONLY)
# And install it, of course ;).
IF(ENABLE_INSTALL)
- INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
+ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
DESTINATION "lib/pkgconfig")
ENDIF()
diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in
index f38601fd7..9bd266753 100644
--- a/Utilities/cmlibarchive/build/cmake/config.h.in
+++ b/Utilities/cmlibarchive/build/cmake/config.h.in
@@ -1,4 +1,5 @@
/* config.h. Generated from build/cmake/config.h.in by cmake configure */
+#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
#if defined(__osf__)
# define _OSF_SOURCE
#endif
@@ -742,6 +743,9 @@
/* Define to 1 if you have the `strchr' function. */
#cmakedefine HAVE_STRCHR 1
+/* Define to 1 if you have the `strnlen' function. */
+#cmakedefine HAVE_STRNLEN 1
+
/* Define to 1 if you have the `strdup' function. */
#cmakedefine HAVE_STRDUP 1
diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version
index 78be3ab7e..205791c6d 100644
--- a/Utilities/cmlibarchive/build/version
+++ b/Utilities/cmlibarchive/build/version
@@ -1 +1 @@
-3004002
+3005001
diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h
index 574e0879a..a1f0b87e0 100644
--- a/Utilities/cmlibarchive/libarchive/archive.h
+++ b/Utilities/cmlibarchive/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3004002
+#define ARCHIVE_VERSION_NUMBER 3005001
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.4.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.5.1"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -243,6 +243,8 @@ typedef int archive_open_callback(struct archive *, void *_client_data);
typedef int archive_close_callback(struct archive *, void *_client_data);
+typedef int archive_free_callback(struct archive *, void *_client_data);
+
/* Switches from one client data object to the next/prev client data object.
* This is useful for reading from different data blocks such as a set of files
* that make up one large file.
@@ -415,6 +417,7 @@ __LA_DECL int archive_read_support_compression_xz(struct archive *)
#endif
__LA_DECL int archive_read_support_filter_all(struct archive *);
+__LA_DECL int archive_read_support_filter_by_code(struct archive *, int);
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
__LA_DECL int archive_read_support_filter_compress(struct archive *);
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
@@ -814,9 +817,13 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch
__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
+/* Deprecated; use archive_write_open2 instead */
__LA_DECL int archive_write_open(struct archive *, void *,
archive_open_callback *, archive_write_callback *,
archive_close_callback *);
+__LA_DECL int archive_write_open2(struct archive *, void *,
+ archive_open_callback *, archive_write_callback *,
+ archive_close_callback *, archive_free_callback *);
__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
__LA_DECL int archive_write_open_filename_w(struct archive *,
diff --git a/Utilities/cmlibarchive/libarchive/archive_acl.c b/Utilities/cmlibarchive/libarchive/archive_acl.c
index 952e20df4..ead7e36e4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_acl.c
+++ b/Utilities/cmlibarchive/libarchive/archive_acl.c
@@ -595,7 +595,7 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags,
else
length += sizeof(uid_t) * 3 + 1;
} else {
- r = archive_mstring_get_mbs_l(&ap->name, &name,
+ r = archive_mstring_get_mbs_l(a, &ap->name, &name,
&len, sc);
if (r != 0)
return (0);
@@ -968,7 +968,7 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
else
prefix = NULL;
r = archive_mstring_get_mbs_l(
- &ap->name, &name, &len, sc);
+ NULL, &ap->name, &name, &len, sc);
if (r != 0) {
free(s);
return (NULL);
@@ -1402,14 +1402,14 @@ isint_w(const wchar_t *start, const wchar_t *end, int *result)
if (start >= end)
return (0);
while (start < end) {
- if (*start < '0' || *start > '9')
+ if (*start < L'0' || *start > L'9')
return (0);
if (n > (INT_MAX / 10) ||
- (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) {
+ (n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) {
n = INT_MAX;
} else {
n *= 10;
- n += *start - '0';
+ n += *start - L'0';
}
start++;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_check_magic.c b/Utilities/cmlibarchive/libarchive/archive_check_magic.c
index 288ce2338..1f40072f8 100644
--- a/Utilities/cmlibarchive/libarchive/archive_check_magic.c
+++ b/Utilities/cmlibarchive/libarchive/archive_check_magic.c
@@ -54,7 +54,7 @@ errmsg(const char *m)
ssize_t written;
while (s > 0) {
- written = write(2, m, strlen(m));
+ written = write(2, m, s);
if (written <= 0)
return;
m += written;
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor.c b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
index 8ab2b0979..d4bca906b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor.c
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor.c
@@ -347,8 +347,31 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
static int
aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
{
+#if NETTLE_VERSION_MAJOR < 3
aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
+#else
+ switch(ctx->key_len) {
+ case AES128_KEY_SIZE:
+ aes128_set_encrypt_key(&ctx->ctx.c128, ctx->key);
+ aes128_encrypt(&ctx->ctx.c128, AES_BLOCK_SIZE, ctx->encr_buf,
+ ctx->nonce);
+ break;
+ case AES192_KEY_SIZE:
+ aes192_set_encrypt_key(&ctx->ctx.c192, ctx->key);
+ aes192_encrypt(&ctx->ctx.c192, AES_BLOCK_SIZE, ctx->encr_buf,
+ ctx->nonce);
+ break;
+ case AES256_KEY_SIZE:
+ aes256_set_encrypt_key(&ctx->ctx.c256, ctx->key);
+ aes256_encrypt(&ctx->ctx.c256, AES_BLOCK_SIZE, ctx->encr_buf,
+ ctx->nonce);
+ break;
+ default:
+ return -1;
+ break;
+ }
+#endif
return 0;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h b/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
index 64a20556a..16b6d16ff 100644
--- a/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_cryptor_private.h
@@ -104,9 +104,18 @@ typedef struct {
#include <nettle/pbkdf2.h>
#endif
#include <nettle/aes.h>
+#include <nettle/version.h>
typedef struct {
+#if NETTLE_VERSION_MAJOR < 3
struct aes_ctx ctx;
+#else
+ union {
+ struct aes128_ctx c128;
+ struct aes192_ctx c192;
+ struct aes256_ctx c256;
+ } ctx;
+#endif
uint8_t key[AES_MAX_KEY_SIZE];
unsigned key_len;
uint8_t nonce[AES_BLOCK_SIZE];
diff --git a/Utilities/cmlibarchive/libarchive/archive_digest.c b/Utilities/cmlibarchive/libarchive/archive_digest.c
index 34c58ac94..410df0156 100644
--- a/Utilities/cmlibarchive/libarchive/archive_digest.c
+++ b/Utilities/cmlibarchive/libarchive/archive_digest.c
@@ -109,14 +109,14 @@ win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
static int
-__archive_libc_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
MD5Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
MD5Update(ctx, indata, insize);
@@ -124,7 +124,7 @@ __archive_libc_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_libc_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
MD5Final(md, ctx);
return (ARCHIVE_OK);
@@ -133,14 +133,14 @@ __archive_libc_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
static int
-__archive_libmd_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
MD5Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
MD5Update(ctx, indata, insize);
@@ -148,7 +148,7 @@ __archive_libmd_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_libmd_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
MD5Final(md, ctx);
return (ARCHIVE_OK);
@@ -157,14 +157,14 @@ __archive_libmd_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
static int
-__archive_libsystem_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
CC_MD5_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
CC_MD5_Update(ctx, indata, insize);
@@ -172,7 +172,7 @@ __archive_libsystem_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_libsystem_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
CC_MD5_Final(md, ctx);
return (ARCHIVE_OK);
@@ -181,7 +181,7 @@ __archive_libsystem_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
static int
-__archive_mbedtls_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
mbedtls_md5_init(ctx);
if (mbedtls_md5_starts_ret(ctx) == 0)
@@ -191,7 +191,7 @@ __archive_mbedtls_md5init(archive_md5_ctx *ctx)
}
static int
-__archive_mbedtls_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
@@ -201,7 +201,7 @@ __archive_mbedtls_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
if (mbedtls_md5_finish_ret(ctx, md) == 0) {
mbedtls_md5_free(ctx);
@@ -215,14 +215,14 @@ __archive_mbedtls_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
static int
-__archive_nettle_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
md5_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
md5_update(ctx, insize, indata);
@@ -230,7 +230,7 @@ __archive_nettle_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
md5_digest(ctx, MD5_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -239,7 +239,7 @@ __archive_nettle_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
static int
-__archive_openssl_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -248,7 +248,7 @@ __archive_openssl_md5init(archive_md5_ctx *ctx)
}
static int
-__archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -256,7 +256,7 @@ __archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
/* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
* this is meant to cope with that. Real fix is probably to fix
@@ -273,20 +273,20 @@ __archive_openssl_md5final(archive_md5_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
static int
-__archive_windowsapi_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
return (win_crypto_init(ctx, CALG_MD5));
}
static int
-__archive_windowsapi_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
-__archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 16, ctx));
}
@@ -294,14 +294,14 @@ __archive_windowsapi_md5final(archive_md5_ctx *ctx, void *md)
#else
static int
-__archive_stub_md5init(archive_md5_ctx *ctx)
+__archive_md5init(archive_md5_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_md5update(archive_md5_ctx *ctx, const void *indata,
+__archive_md5update(archive_md5_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -311,7 +311,7 @@ __archive_stub_md5update(archive_md5_ctx *ctx, const void *indata,
}
static int
-__archive_stub_md5final(archive_md5_ctx *ctx, void *md)
+__archive_md5final(archive_md5_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -324,14 +324,14 @@ __archive_stub_md5final(archive_md5_ctx *ctx, void *md)
#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
static int
-__archive_libc_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
RMD160Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
RMD160Update(ctx, indata, insize);
@@ -339,7 +339,7 @@ __archive_libc_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
RMD160Final(md, ctx);
return (ARCHIVE_OK);
@@ -348,14 +348,14 @@ __archive_libc_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
static int
-__archive_libmd_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
RIPEMD160_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
RIPEMD160_Update(ctx, indata, insize);
@@ -363,7 +363,7 @@ __archive_libmd_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
RIPEMD160_Final(md, ctx);
return (ARCHIVE_OK);
@@ -372,7 +372,7 @@ __archive_libmd_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
static int
-__archive_mbedtls_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
mbedtls_ripemd160_init(ctx);
if (mbedtls_ripemd160_starts_ret(ctx) == 0)
@@ -382,7 +382,7 @@ __archive_mbedtls_ripemd160init(archive_rmd160_ctx *ctx)
}
static int
-__archive_mbedtls_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
@@ -392,7 +392,7 @@ __archive_mbedtls_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
mbedtls_ripemd160_free(ctx);
@@ -406,14 +406,14 @@ __archive_mbedtls_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
static int
-__archive_nettle_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
ripemd160_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
ripemd160_update(ctx, insize, indata);
@@ -421,7 +421,7 @@ __archive_nettle_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -430,7 +430,7 @@ __archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
static int
-__archive_openssl_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -439,7 +439,7 @@ __archive_openssl_ripemd160init(archive_rmd160_ctx *ctx)
}
static int
-__archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -447,7 +447,7 @@ __archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
if (*ctx) {
EVP_DigestFinal(*ctx, md, NULL);
@@ -460,14 +460,14 @@ __archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#else
static int
-__archive_stub_ripemd160init(archive_rmd160_ctx *ctx)
+__archive_ripemd160init(archive_rmd160_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
+__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -477,7 +477,7 @@ __archive_stub_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
}
static int
-__archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md)
+__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -490,14 +490,14 @@ __archive_stub_ripemd160final(archive_rmd160_ctx *ctx, void *md)
#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
static int
-__archive_libc_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
SHA1Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
SHA1Update(ctx, indata, insize);
@@ -505,7 +505,7 @@ __archive_libc_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_libc_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
SHA1Final(md, ctx);
return (ARCHIVE_OK);
@@ -514,14 +514,14 @@ __archive_libc_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
static int
-__archive_libmd_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
SHA1_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
SHA1_Update(ctx, indata, insize);
@@ -529,7 +529,7 @@ __archive_libmd_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
SHA1_Final(md, ctx);
return (ARCHIVE_OK);
@@ -538,14 +538,14 @@ __archive_libmd_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
static int
-__archive_libsystem_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
CC_SHA1_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
CC_SHA1_Update(ctx, indata, insize);
@@ -553,7 +553,7 @@ __archive_libsystem_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
CC_SHA1_Final(md, ctx);
return (ARCHIVE_OK);
@@ -562,7 +562,7 @@ __archive_libsystem_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
static int
-__archive_mbedtls_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
mbedtls_sha1_init(ctx);
if (mbedtls_sha1_starts_ret(ctx) == 0)
@@ -572,7 +572,7 @@ __archive_mbedtls_sha1init(archive_sha1_ctx *ctx)
}
static int
-__archive_mbedtls_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
@@ -582,7 +582,7 @@ __archive_mbedtls_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
mbedtls_sha1_free(ctx);
@@ -596,14 +596,14 @@ __archive_mbedtls_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
static int
-__archive_nettle_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
sha1_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
sha1_update(ctx, insize, indata);
@@ -611,7 +611,7 @@ __archive_nettle_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
sha1_digest(ctx, SHA1_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -620,7 +620,7 @@ __archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
static int
-__archive_openssl_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -629,7 +629,7 @@ __archive_openssl_sha1init(archive_sha1_ctx *ctx)
}
static int
-__archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -637,7 +637,7 @@ __archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
/* HACK: archive_write_set_format_xar.c is finalizing empty contexts, so
* this is meant to cope with that. Real fix is probably to fix
@@ -654,20 +654,20 @@ __archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
static int
-__archive_windowsapi_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
return (win_crypto_init(ctx, CALG_SHA1));
}
static int
-__archive_windowsapi_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
-__archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 20, ctx));
}
@@ -675,14 +675,14 @@ __archive_windowsapi_sha1final(archive_sha1_ctx *ctx, void *md)
#else
static int
-__archive_stub_sha1init(archive_sha1_ctx *ctx)
+__archive_sha1init(archive_sha1_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata,
+__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -692,7 +692,7 @@ __archive_stub_sha1update(archive_sha1_ctx *ctx, const void *indata,
}
static int
-__archive_stub_sha1final(archive_sha1_ctx *ctx, void *md)
+__archive_sha1final(archive_sha1_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -705,14 +705,14 @@ __archive_stub_sha1final(archive_sha1_ctx *ctx, void *md)
#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
static int
-__archive_libc_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
SHA256_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
SHA256_Update(ctx, indata, insize);
@@ -720,7 +720,7 @@ __archive_libc_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_libc_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
SHA256_Final(md, ctx);
return (ARCHIVE_OK);
@@ -729,14 +729,14 @@ __archive_libc_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
static int
-__archive_libc2_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
SHA256Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
SHA256Update(ctx, indata, insize);
@@ -744,7 +744,7 @@ __archive_libc2_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
SHA256Final(md, ctx);
return (ARCHIVE_OK);
@@ -753,14 +753,14 @@ __archive_libc2_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
static int
-__archive_libc3_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
SHA256Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
SHA256Update(ctx, indata, insize);
@@ -768,7 +768,7 @@ __archive_libc3_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
SHA256Final(md, ctx);
return (ARCHIVE_OK);
@@ -777,14 +777,14 @@ __archive_libc3_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
static int
-__archive_libmd_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
SHA256_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
SHA256_Update(ctx, indata, insize);
@@ -792,7 +792,7 @@ __archive_libmd_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
SHA256_Final(md, ctx);
return (ARCHIVE_OK);
@@ -801,14 +801,14 @@ __archive_libmd_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
static int
-__archive_libsystem_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
CC_SHA256_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
CC_SHA256_Update(ctx, indata, insize);
@@ -816,7 +816,7 @@ __archive_libsystem_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
CC_SHA256_Final(md, ctx);
return (ARCHIVE_OK);
@@ -825,7 +825,7 @@ __archive_libsystem_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
static int
-__archive_mbedtls_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
mbedtls_sha256_init(ctx);
if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
@@ -835,7 +835,7 @@ __archive_mbedtls_sha256init(archive_sha256_ctx *ctx)
}
static int
-__archive_mbedtls_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
@@ -845,7 +845,7 @@ __archive_mbedtls_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
mbedtls_sha256_free(ctx);
@@ -859,14 +859,14 @@ __archive_mbedtls_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
static int
-__archive_nettle_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
sha256_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
sha256_update(ctx, insize, indata);
@@ -874,7 +874,7 @@ __archive_nettle_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
sha256_digest(ctx, SHA256_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -883,7 +883,7 @@ __archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
static int
-__archive_openssl_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -892,7 +892,7 @@ __archive_openssl_sha256init(archive_sha256_ctx *ctx)
}
static int
-__archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -900,7 +900,7 @@ __archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
if (*ctx) {
EVP_DigestFinal(*ctx, md, NULL);
@@ -913,20 +913,20 @@ __archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
static int
-__archive_windowsapi_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
return (win_crypto_init(ctx, CALG_SHA_256));
}
static int
-__archive_windowsapi_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
-__archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 32, ctx));
}
@@ -934,14 +934,14 @@ __archive_windowsapi_sha256final(archive_sha256_ctx *ctx, void *md)
#else
static int
-__archive_stub_sha256init(archive_sha256_ctx *ctx)
+__archive_sha256init(archive_sha256_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata,
+__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -951,7 +951,7 @@ __archive_stub_sha256update(archive_sha256_ctx *ctx, const void *indata,
}
static int
-__archive_stub_sha256final(archive_sha256_ctx *ctx, void *md)
+__archive_sha256final(archive_sha256_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -964,14 +964,14 @@ __archive_stub_sha256final(archive_sha256_ctx *ctx, void *md)
#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
static int
-__archive_libc_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
SHA384_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
SHA384_Update(ctx, indata, insize);
@@ -979,7 +979,7 @@ __archive_libc_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_libc_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
SHA384_Final(md, ctx);
return (ARCHIVE_OK);
@@ -988,14 +988,14 @@ __archive_libc_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
static int
-__archive_libc2_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
SHA384Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
SHA384Update(ctx, indata, insize);
@@ -1003,7 +1003,7 @@ __archive_libc2_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
SHA384Final(md, ctx);
return (ARCHIVE_OK);
@@ -1012,14 +1012,14 @@ __archive_libc2_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
static int
-__archive_libc3_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
SHA384Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
SHA384Update(ctx, indata, insize);
@@ -1027,7 +1027,7 @@ __archive_libc3_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
SHA384Final(md, ctx);
return (ARCHIVE_OK);
@@ -1036,14 +1036,14 @@ __archive_libc3_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
static int
-__archive_libsystem_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
CC_SHA384_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
CC_SHA384_Update(ctx, indata, insize);
@@ -1051,7 +1051,7 @@ __archive_libsystem_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
CC_SHA384_Final(md, ctx);
return (ARCHIVE_OK);
@@ -1060,7 +1060,7 @@ __archive_libsystem_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
static int
-__archive_mbedtls_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
mbedtls_sha512_init(ctx);
if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
@@ -1070,7 +1070,7 @@ __archive_mbedtls_sha384init(archive_sha384_ctx *ctx)
}
static int
-__archive_mbedtls_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
@@ -1080,7 +1080,7 @@ __archive_mbedtls_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
mbedtls_sha512_free(ctx);
@@ -1094,14 +1094,14 @@ __archive_mbedtls_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
static int
-__archive_nettle_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
sha384_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
sha384_update(ctx, insize, indata);
@@ -1109,7 +1109,7 @@ __archive_nettle_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
sha384_digest(ctx, SHA384_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -1118,7 +1118,7 @@ __archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
static int
-__archive_openssl_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -1127,7 +1127,7 @@ __archive_openssl_sha384init(archive_sha384_ctx *ctx)
}
static int
-__archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -1135,7 +1135,7 @@ __archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
if (*ctx) {
EVP_DigestFinal(*ctx, md, NULL);
@@ -1148,20 +1148,20 @@ __archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
static int
-__archive_windowsapi_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
return (win_crypto_init(ctx, CALG_SHA_384));
}
static int
-__archive_windowsapi_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
-__archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 48, ctx));
}
@@ -1169,14 +1169,14 @@ __archive_windowsapi_sha384final(archive_sha384_ctx *ctx, void *md)
#else
static int
-__archive_stub_sha384init(archive_sha384_ctx *ctx)
+__archive_sha384init(archive_sha384_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata,
+__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -1186,7 +1186,7 @@ __archive_stub_sha384update(archive_sha384_ctx *ctx, const void *indata,
}
static int
-__archive_stub_sha384final(archive_sha384_ctx *ctx, void *md)
+__archive_sha384final(archive_sha384_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -1199,14 +1199,14 @@ __archive_stub_sha384final(archive_sha384_ctx *ctx, void *md)
#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
static int
-__archive_libc_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
SHA512_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
SHA512_Update(ctx, indata, insize);
@@ -1214,7 +1214,7 @@ __archive_libc_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_libc_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
SHA512_Final(md, ctx);
return (ARCHIVE_OK);
@@ -1223,14 +1223,14 @@ __archive_libc_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
static int
-__archive_libc2_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
SHA512Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
SHA512Update(ctx, indata, insize);
@@ -1238,7 +1238,7 @@ __archive_libc2_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
SHA512Final(md, ctx);
return (ARCHIVE_OK);
@@ -1247,14 +1247,14 @@ __archive_libc2_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
static int
-__archive_libc3_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
SHA512Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
SHA512Update(ctx, indata, insize);
@@ -1262,7 +1262,7 @@ __archive_libc3_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
SHA512Final(md, ctx);
return (ARCHIVE_OK);
@@ -1271,14 +1271,14 @@ __archive_libc3_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
static int
-__archive_libmd_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
SHA512_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
SHA512_Update(ctx, indata, insize);
@@ -1286,7 +1286,7 @@ __archive_libmd_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
SHA512_Final(md, ctx);
return (ARCHIVE_OK);
@@ -1295,14 +1295,14 @@ __archive_libmd_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
static int
-__archive_libsystem_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
CC_SHA512_Init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
CC_SHA512_Update(ctx, indata, insize);
@@ -1310,7 +1310,7 @@ __archive_libsystem_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
CC_SHA512_Final(md, ctx);
return (ARCHIVE_OK);
@@ -1319,7 +1319,7 @@ __archive_libsystem_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
static int
-__archive_mbedtls_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
mbedtls_sha512_init(ctx);
if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
@@ -1329,7 +1329,7 @@ __archive_mbedtls_sha512init(archive_sha512_ctx *ctx)
}
static int
-__archive_mbedtls_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
@@ -1339,7 +1339,7 @@ __archive_mbedtls_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_mbedtls_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
mbedtls_sha512_free(ctx);
@@ -1353,14 +1353,14 @@ __archive_mbedtls_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
static int
-__archive_nettle_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
sha512_init(ctx);
return (ARCHIVE_OK);
}
static int
-__archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
sha512_update(ctx, insize, indata);
@@ -1368,7 +1368,7 @@ __archive_nettle_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
sha512_digest(ctx, SHA512_DIGEST_SIZE, md);
return (ARCHIVE_OK);
@@ -1377,7 +1377,7 @@ __archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
static int
-__archive_openssl_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
if ((*ctx = EVP_MD_CTX_new()) == NULL)
return (ARCHIVE_FAILED);
@@ -1386,7 +1386,7 @@ __archive_openssl_sha512init(archive_sha512_ctx *ctx)
}
static int
-__archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
EVP_DigestUpdate(*ctx, indata, insize);
@@ -1394,7 +1394,7 @@ __archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
if (*ctx) {
EVP_DigestFinal(*ctx, md, NULL);
@@ -1407,20 +1407,20 @@ __archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md)
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
static int
-__archive_windowsapi_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
return (win_crypto_init(ctx, CALG_SHA_512));
}
static int
-__archive_windowsapi_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
return (win_crypto_Update(ctx, indata, insize));
}
static int
-__archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
return (win_crypto_Final(md, 64, ctx));
}
@@ -1428,14 +1428,14 @@ __archive_windowsapi_sha512final(archive_sha512_ctx *ctx, void *md)
#else
static int
-__archive_stub_sha512init(archive_sha512_ctx *ctx)
+__archive_sha512init(archive_sha512_ctx *ctx)
{
(void)ctx; /* UNUSED */
return (ARCHIVE_FAILED);
}
static int
-__archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata,
+__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
size_t insize)
{
(void)ctx; /* UNUSED */
@@ -1445,7 +1445,7 @@ __archive_stub_sha512update(archive_sha512_ctx *ctx, const void *indata,
}
static int
-__archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
+__archive_sha512final(archive_sha512_ctx *ctx, void *md)
{
(void)ctx; /* UNUSED */
(void)md; /* UNUSED */
@@ -1468,224 +1468,32 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md)
const struct archive_digest __archive_digest =
{
/* MD5 */
-#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
- &__archive_libc_md5init,
- &__archive_libc_md5update,
- &__archive_libc_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
- &__archive_libmd_md5init,
- &__archive_libmd_md5update,
- &__archive_libmd_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
- &__archive_libsystem_md5init,
- &__archive_libsystem_md5update,
- &__archive_libsystem_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
- &__archive_mbedtls_md5init,
- &__archive_mbedtls_md5update,
- &__archive_mbedtls_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
- &__archive_nettle_md5init,
- &__archive_nettle_md5update,
- &__archive_nettle_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
- &__archive_openssl_md5init,
- &__archive_openssl_md5update,
- &__archive_openssl_md5final,
-#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
- &__archive_windowsapi_md5init,
- &__archive_windowsapi_md5update,
- &__archive_windowsapi_md5final,
-#elif !defined(ARCHIVE_MD5_COMPILE_TEST)
- &__archive_stub_md5init,
- &__archive_stub_md5update,
- &__archive_stub_md5final,
-#endif
+ &__archive_md5init,
+ &__archive_md5update,
+ &__archive_md5final,
/* RIPEMD160 */
-#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
- &__archive_libc_ripemd160init,
- &__archive_libc_ripemd160update,
- &__archive_libc_ripemd160final,
-#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
- &__archive_libmd_ripemd160init,
- &__archive_libmd_ripemd160update,
- &__archive_libmd_ripemd160final,
-#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
- &__archive_mbedtls_ripemd160init,
- &__archive_mbedtls_ripemd160update,
- &__archive_mbedtls_ripemd160final,
-#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
- &__archive_nettle_ripemd160init,
- &__archive_nettle_ripemd160update,
- &__archive_nettle_ripemd160final,
-#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
- &__archive_openssl_ripemd160init,
- &__archive_openssl_ripemd160update,
- &__archive_openssl_ripemd160final,
-#elif !defined(ARCHIVE_RMD160_COMPILE_TEST)
- &__archive_stub_ripemd160init,
- &__archive_stub_ripemd160update,
- &__archive_stub_ripemd160final,
-#endif
+ &__archive_ripemd160init,
+ &__archive_ripemd160update,
+ &__archive_ripemd160final,
/* SHA1 */
-#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
- &__archive_libc_sha1init,
- &__archive_libc_sha1update,
- &__archive_libc_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
- &__archive_libmd_sha1init,
- &__archive_libmd_sha1update,
- &__archive_libmd_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
- &__archive_libsystem_sha1init,
- &__archive_libsystem_sha1update,
- &__archive_libsystem_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
- &__archive_mbedtls_sha1init,
- &__archive_mbedtls_sha1update,
- &__archive_mbedtls_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
- &__archive_nettle_sha1init,
- &__archive_nettle_sha1update,
- &__archive_nettle_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
- &__archive_openssl_sha1init,
- &__archive_openssl_sha1update,
- &__archive_openssl_sha1final,
-#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
- &__archive_windowsapi_sha1init,
- &__archive_windowsapi_sha1update,
- &__archive_windowsapi_sha1final,
-#elif !defined(ARCHIVE_SHA1_COMPILE_TEST)
- &__archive_stub_sha1init,
- &__archive_stub_sha1update,
- &__archive_stub_sha1final,
-#endif
+ &__archive_sha1init,
+ &__archive_sha1update,
+ &__archive_sha1final,
/* SHA256 */
-#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
- &__archive_libc_sha256init,
- &__archive_libc_sha256update,
- &__archive_libc_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
- &__archive_libc2_sha256init,
- &__archive_libc2_sha256update,
- &__archive_libc2_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
- &__archive_libc3_sha256init,
- &__archive_libc3_sha256update,
- &__archive_libc3_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
- &__archive_libmd_sha256init,
- &__archive_libmd_sha256update,
- &__archive_libmd_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
- &__archive_libsystem_sha256init,
- &__archive_libsystem_sha256update,
- &__archive_libsystem_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
- &__archive_mbedtls_sha256init,
- &__archive_mbedtls_sha256update,
- &__archive_mbedtls_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
- &__archive_nettle_sha256init,
- &__archive_nettle_sha256update,
- &__archive_nettle_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
- &__archive_openssl_sha256init,
- &__archive_openssl_sha256update,
- &__archive_openssl_sha256final,
-#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
- &__archive_windowsapi_sha256init,
- &__archive_windowsapi_sha256update,
- &__archive_windowsapi_sha256final,
-#elif !defined(ARCHIVE_SHA256_COMPILE_TEST)
- &__archive_stub_sha256init,
- &__archive_stub_sha256update,
- &__archive_stub_sha256final,
-#endif
+ &__archive_sha256init,
+ &__archive_sha256update,
+ &__archive_sha256final,
/* SHA384 */
-#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
- &__archive_libc_sha384init,
- &__archive_libc_sha384update,
- &__archive_libc_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
- &__archive_libc2_sha384init,
- &__archive_libc2_sha384update,
- &__archive_libc2_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
- &__archive_libc3_sha384init,
- &__archive_libc3_sha384update,
- &__archive_libc3_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
- &__archive_libsystem_sha384init,
- &__archive_libsystem_sha384update,
- &__archive_libsystem_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
- &__archive_mbedtls_sha384init,
- &__archive_mbedtls_sha384update,
- &__archive_mbedtls_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
- &__archive_nettle_sha384init,
- &__archive_nettle_sha384update,
- &__archive_nettle_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
- &__archive_openssl_sha384init,
- &__archive_openssl_sha384update,
- &__archive_openssl_sha384final,
-#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
- &__archive_windowsapi_sha384init,
- &__archive_windowsapi_sha384update,
- &__archive_windowsapi_sha384final,
-#elif !defined(ARCHIVE_SHA384_COMPILE_TEST)
- &__archive_stub_sha384init,
- &__archive_stub_sha384update,
- &__archive_stub_sha384final,
-#endif
+ &__archive_sha384init,
+ &__archive_sha384update,
+ &__archive_sha384final,
/* SHA512 */
-#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
- &__archive_libc_sha512init,
- &__archive_libc_sha512update,
- &__archive_libc_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
- &__archive_libc2_sha512init,
- &__archive_libc2_sha512update,
- &__archive_libc2_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
- &__archive_libc3_sha512init,
- &__archive_libc3_sha512update,
- &__archive_libc3_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
- &__archive_libmd_sha512init,
- &__archive_libmd_sha512update,
- &__archive_libmd_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
- &__archive_libsystem_sha512init,
- &__archive_libsystem_sha512update,
- &__archive_libsystem_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
- &__archive_mbedtls_sha512init,
- &__archive_mbedtls_sha512update,
- &__archive_mbedtls_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
- &__archive_nettle_sha512init,
- &__archive_nettle_sha512update,
- &__archive_nettle_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
- &__archive_openssl_sha512init,
- &__archive_openssl_sha512update,
- &__archive_openssl_sha512final
-#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
- &__archive_windowsapi_sha512init,
- &__archive_windowsapi_sha512update,
- &__archive_windowsapi_sha512final
-#elif !defined(ARCHIVE_SHA512_COMPILE_TEST)
- &__archive_stub_sha512init,
- &__archive_stub_sha512update,
- &__archive_stub_sha512final
-#endif
+ &__archive_sha512init,
+ &__archive_sha512update,
+ &__archive_sha512final
};
diff --git a/Utilities/cmlibarchive/libarchive/archive_digest_private.h b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
index 15312ee9a..9b3bd6621 100644
--- a/Utilities/cmlibarchive/libarchive/archive_digest_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_digest_private.h
@@ -30,6 +30,10 @@
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
+#ifndef __LIBARCHIVE_CONFIG_H_INCLUDED
+#error "Should have include config.h first!"
+#endif
+
/*
* Crypto support in various Operating Systems:
*
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c
index a15e98c28..ca7a4bdb5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.c
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.c
@@ -208,6 +208,19 @@ archive_entry_clone(struct archive_entry *entry)
/* Copy encryption status */
entry2->encryption = entry->encryption;
+
+ /* Copy digests */
+#define copy_digest(_e2, _e, _t) \
+ memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t))
+
+ copy_digest(entry2, entry, md5);
+ copy_digest(entry2, entry, rmd160);
+ copy_digest(entry2, entry, sha1);
+ copy_digest(entry2, entry, sha256);
+ copy_digest(entry2, entry, sha384);
+ copy_digest(entry2, entry, sha512);
+
+#undef copy_digest
/* Copy ACL data over. */
archive_acl_copy(&entry2->acl, &entry->acl);
@@ -353,7 +366,7 @@ archive_entry_devminor(struct archive_entry *entry)
return minor(entry->ae_stat.aest_dev);
}
-mode_t
+__LA_MODE_T
archive_entry_filetype(struct archive_entry *entry)
{
return (AE_IFMT & entry->acl.mode);
@@ -450,7 +463,7 @@ int
_archive_entry_gname_l(struct archive_entry *entry,
const char **p, size_t *len, struct archive_string_conv *sc)
{
- return (archive_mstring_get_mbs_l(&entry->ae_gname, p, len, sc));
+ return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc));
}
const char *
@@ -504,7 +517,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry,
*len = 0;
return (0);
}
- return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc));
+ return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_hardlink, p, len, sc));
}
la_int64_t
@@ -525,7 +538,7 @@ archive_entry_ino64(struct archive_entry *entry)
return (entry->ae_stat.aest_ino);
}
-mode_t
+__LA_MODE_T
archive_entry_mode(struct archive_entry *entry)
{
return (entry->acl.mode);
@@ -595,10 +608,10 @@ int
_archive_entry_pathname_l(struct archive_entry *entry,
const char **p, size_t *len, struct archive_string_conv *sc)
{
- return (archive_mstring_get_mbs_l(&entry->ae_pathname, p, len, sc));
+ return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc));
}
-mode_t
+__LA_MODE_T
archive_entry_perm(struct archive_entry *entry)
{
return (~AE_IFMT & entry->acl.mode);
@@ -723,7 +736,7 @@ _archive_entry_symlink_l(struct archive_entry *entry,
*len = 0;
return (0);
}
- return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc));
+ return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_symlink, p, len, sc));
}
la_int64_t
@@ -769,7 +782,7 @@ int
_archive_entry_uname_l(struct archive_entry *entry,
const char **p, size_t *len, struct archive_string_conv *sc)
{
- return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
+ return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc));
}
int
@@ -1416,6 +1429,62 @@ archive_entry_copy_mac_metadata(struct archive_entry *entry,
}
}
+/* Digest handling */
+const unsigned char *
+archive_entry_digest(struct archive_entry *entry, int type)
+{
+ switch (type) {
+ case ARCHIVE_ENTRY_DIGEST_MD5:
+ return entry->digest.md5;
+ case ARCHIVE_ENTRY_DIGEST_RMD160:
+ return entry->digest.rmd160;
+ case ARCHIVE_ENTRY_DIGEST_SHA1:
+ return entry->digest.sha1;
+ case ARCHIVE_ENTRY_DIGEST_SHA256:
+ return entry->digest.sha256;
+ case ARCHIVE_ENTRY_DIGEST_SHA384:
+ return entry->digest.sha384;
+ case ARCHIVE_ENTRY_DIGEST_SHA512:
+ return entry->digest.sha512;
+ default:
+ return NULL;
+ }
+}
+
+int
+archive_entry_set_digest(struct archive_entry *entry, int type,
+ const unsigned char *digest)
+{
+#define copy_digest(_e, _t, _d)\
+ memcpy(_e->digest._t, _d, sizeof(_e->digest._t))
+
+ switch (type) {
+ case ARCHIVE_ENTRY_DIGEST_MD5:
+ copy_digest(entry, md5, digest);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_RMD160:
+ copy_digest(entry, rmd160, digest);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA1:
+ copy_digest(entry, sha1, digest);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA256:
+ copy_digest(entry, sha256, digest);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA384:
+ copy_digest(entry, sha384, digest);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA512:
+ copy_digest(entry, sha512, digest);
+ break;
+ default:
+ return ARCHIVE_WARN;
+ }
+
+ return ARCHIVE_OK;
+#undef copy_digest
+}
+
/*
* ACL management. The following would, of course, be a lot simpler
* if: 1) the last draft of POSIX.1e were a really thorough and
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h
index 0053faa19..21e89d2e7 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry.h
@@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3004002
+#define ARCHIVE_VERSION_NUMBER 3005001
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -394,6 +394,19 @@ __LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t
__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
/*
+ * Digest routine. This is used to query the raw hex digest for the
+ * given entry. The type of digest is provided as an argument.
+ */
+#define ARCHIVE_ENTRY_DIGEST_MD5 0x00000001
+#define ARCHIVE_ENTRY_DIGEST_RMD160 0x00000002
+#define ARCHIVE_ENTRY_DIGEST_SHA1 0x00000003
+#define ARCHIVE_ENTRY_DIGEST_SHA256 0x00000004
+#define ARCHIVE_ENTRY_DIGEST_SHA384 0x00000005
+#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006
+
+__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
+
+/*
* ACL routines. This used to simply store and return text-format ACL
* strings, but that proved insufficient for a number of reasons:
* = clients need control over uname/uid and gname/gid mappings
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_private.h b/Utilities/cmlibarchive/libarchive/archive_entry_private.h
index 2b9a084ca..cf4deb24e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_private.h
@@ -50,6 +50,15 @@ struct ae_sparse {
int64_t length;
};
+struct ae_digest {
+ unsigned char md5[16];
+ unsigned char rmd160[20];
+ unsigned char sha1[20];
+ unsigned char sha256[32];
+ unsigned char sha384[48];
+ unsigned char sha512[64];
+};
+
/*
* Description of an archive entry.
*
@@ -162,6 +171,9 @@ struct archive_entry {
void *mac_metadata;
size_t mac_metadata_size;
+ /* Digest support. */
+ struct ae_digest digest;
+
/* ACL support. */
struct archive_acl acl;
@@ -181,4 +193,8 @@ struct archive_entry {
int ae_symlink_type;
};
+int
+archive_entry_set_digest(struct archive_entry *entry, int type,
+ const unsigned char *digest);
+
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3 b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
index aa5c8e03f..29a53f756 100644
--- a/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
+++ b/Utilities/cmlibarchive/libarchive/archive_entry_stat.3
@@ -215,9 +215,9 @@ and
set and unset the size, respectively.
.Pp
The number of references (hardlinks) can be obtained by calling
-.Fn archive_entry_nlinks
+.Fn archive_entry_nlink
and set with
-.Fn archive_entry_set_nlinks .
+.Fn archive_entry_set_nlink .
.Ss Identifying unique files
The functions
.Fn archive_entry_dev
diff --git a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
index 4029395b4..cc3f77820 100644
--- a/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
+++ b/Utilities/cmlibarchive/libarchive/archive_ppmd7.c
@@ -4,7 +4,7 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "archive_platform.h"
-#include <memory.h>
+#include <stdlib.h>
#include "archive_ppmd7_private.h"
diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c
index 4a933b2fc..c59f05153 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read.c
@@ -892,15 +892,16 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
len = a->read_data_remaining;
if (len > s)
len = s;
- if (len)
+ if (len) {
memcpy(dest, a->read_data_block, len);
- s -= len;
- a->read_data_block += len;
- a->read_data_remaining -= len;
- a->read_data_output_offset += len;
- a->read_data_offset += len;
- dest += len;
- bytes_read += len;
+ s -= len;
+ a->read_data_block += len;
+ a->read_data_remaining -= len;
+ a->read_data_output_offset += len;
+ a->read_data_offset += len;
+ dest += len;
+ bytes_read += len;
+ }
}
}
a->read_data_is_posix_read = 0;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
index cf821b5d4..f0b1ab933 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_add_passphrase.c
@@ -57,6 +57,10 @@ insert_passphrase_to_head(struct archive_read *a,
{
p->next = a->passphrases.first;
a->passphrases.first = p;
+ if (&a->passphrases.first == a->passphrases.last) {
+ a->passphrases.last = &p->next;
+ p->next = NULL;
+ }
}
static struct archive_read_passphrase *
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
index 2a8cec8d1..9c9cf38ee 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c
@@ -103,6 +103,10 @@ __FBSDID("$FreeBSD");
static int setup_mac_metadata(struct archive_read_disk *,
struct archive_entry *, int *fd);
+#ifdef ARCHIVE_XATTR_FREEBSD
+static int setup_xattrs_namespace(struct archive_read_disk *,
+ struct archive_entry *, int *, int);
+#endif
static int setup_xattrs(struct archive_read_disk *,
struct archive_entry *, int *fd);
static int setup_sparse(struct archive_read_disk *,
@@ -701,14 +705,13 @@ setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
}
static int
-setup_xattrs(struct archive_read_disk *a,
- struct archive_entry *entry, int *fd)
+setup_xattrs_namespace(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd, int namespace)
{
char buff[512];
char *list, *p;
ssize_t list_size;
const char *path;
- int namespace = EXTATTR_NAMESPACE_USER;
path = NULL;
@@ -727,6 +730,8 @@ setup_xattrs(struct archive_read_disk *a,
if (list_size == -1 && errno == EOPNOTSUPP)
return (ARCHIVE_OK);
+ if (list_size == -1 && errno == EPERM)
+ return (ARCHIVE_OK);
if (list_size == -1) {
archive_set_error(&a->archive, errno,
"Couldn't list extended attributes");
@@ -760,7 +765,17 @@ setup_xattrs(struct archive_read_disk *a,
size_t len = 255 & (int)*p;
char *name;
- strcpy(buff, "user.");
+ if (namespace == EXTATTR_NAMESPACE_SYSTEM) {
+ if (!strcmp(p + 1, "nfs4.acl") ||
+ !strcmp(p + 1, "posix1e.acl_access") ||
+ !strcmp(p + 1, "posix1e.acl_default")) {
+ p += 1 + len;
+ continue;
+ }
+ strcpy(buff, "system.");
+ } else {
+ strcpy(buff, "user.");
+ }
name = buff + strlen(buff);
memcpy(name, p + 1, len);
name[len] = '\0';
@@ -772,6 +787,31 @@ setup_xattrs(struct archive_read_disk *a,
return (ARCHIVE_OK);
}
+static int
+setup_xattrs(struct archive_read_disk *a,
+ struct archive_entry *entry, int *fd)
+{
+ int namespaces[2];
+ int i, res;
+
+ namespaces[0] = EXTATTR_NAMESPACE_USER;
+ namespaces[1] = EXTATTR_NAMESPACE_SYSTEM;
+
+ for (i = 0; i < 2; i++) {
+ res = setup_xattrs_namespace(a, entry, fd,
+ namespaces[i]);
+ switch (res) {
+ case (ARCHIVE_OK):
+ case (ARCHIVE_WARN):
+ break;
+ default:
+ return (res);
+ }
+ }
+
+ return (ARCHIVE_OK);
+}
+
#else
/*
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
index 52fec7bb4..289820695 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
@@ -1658,7 +1658,7 @@ static int
setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
- struct statvfs sfs;
+ struct statvfs svfs;
int r, xr = 0;
t->current_filesystem->synthetic = -1;
@@ -1667,16 +1667,16 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
}
if (tree_current_is_symblic_link_target(t)) {
- r = statvfs(tree_current_access_path(t), &sfs);
+ r = statvfs(tree_current_access_path(t), &svfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
} else {
#ifdef HAVE_FSTATVFS
- r = fstatvfs(tree_current_dir_fd(t), &sfs);
+ r = fstatvfs(tree_current_dir_fd(t), &svfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
#else
- r = statvfs(".", &sfs);
+ r = statvfs(".", &svfs);
if (r == 0)
xr = get_xfer_size(t, -1, ".");
#endif
@@ -1688,30 +1688,30 @@ setup_current_filesystem(struct archive_read_disk *a)
} else if (xr == 1) {
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
* for pathconf() function. */
- t->current_filesystem->xfer_align = sfs.f_frsize;
+ t->current_filesystem->xfer_align = svfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
- t->current_filesystem->min_xfer_size = sfs.f_iosize;
- t->current_filesystem->incr_xfer_size = sfs.f_iosize;
+ t->current_filesystem->min_xfer_size = svfs.f_iosize;
+ t->current_filesystem->incr_xfer_size = svfs.f_iosize;
#else
- t->current_filesystem->min_xfer_size = sfs.f_bsize;
- t->current_filesystem->incr_xfer_size = sfs.f_bsize;
+ t->current_filesystem->min_xfer_size = svfs.f_bsize;
+ t->current_filesystem->incr_xfer_size = svfs.f_bsize;
#endif
}
- if (sfs.f_flag & ST_LOCAL)
+ if (svfs.f_flag & ST_LOCAL)
t->current_filesystem->remote = 0;
else
t->current_filesystem->remote = 1;
#if defined(ST_NOATIME)
- if (sfs.f_flag & ST_NOATIME)
+ if (svfs.f_flag & ST_NOATIME)
t->current_filesystem->noatime = 1;
else
#endif
t->current_filesystem->noatime = 0;
/* Set maximum filename length. */
- t->current_filesystem->name_max = sfs.f_namemax;
+ t->current_filesystem->name_max = svfs.f_namemax;
return (ARCHIVE_OK);
}
@@ -1840,7 +1840,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(HAVE_STATVFS)
if (svfs.f_flag & ST_NOATIME)
#else
- if (sfs.f_flag & ST_NOATIME)
+ if (sfs.f_flags & ST_NOATIME)
#endif
t->current_filesystem->noatime = 1;
else
@@ -1864,7 +1864,7 @@ static int
setup_current_filesystem(struct archive_read_disk *a)
{
struct tree *t = a->tree;
- struct statvfs sfs;
+ struct statvfs svfs;
int r, xr = 0;
t->current_filesystem->synthetic = -1;/* Not supported */
@@ -1883,7 +1883,7 @@ setup_current_filesystem(struct archive_read_disk *a)
"openat failed");
return (ARCHIVE_FAILED);
}
- r = fstatvfs(fd, &sfs);
+ r = fstatvfs(fd, &svfs);
if (r == 0)
xr = get_xfer_size(t, fd, NULL);
close(fd);
@@ -1892,13 +1892,13 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
- r = statvfs(tree_current_access_path(t), &sfs);
+ r = statvfs(tree_current_access_path(t), &svfs);
if (r == 0)
xr = get_xfer_size(t, -1, tree_current_access_path(t));
#endif
} else {
#ifdef HAVE_FSTATVFS
- r = fstatvfs(tree_current_dir_fd(t), &sfs);
+ r = fstatvfs(tree_current_dir_fd(t), &svfs);
if (r == 0)
xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
#else
@@ -1906,7 +1906,7 @@ setup_current_filesystem(struct archive_read_disk *a)
archive_set_error(&a->archive, errno, "fchdir failed");
return (ARCHIVE_FAILED);
}
- r = statvfs(".", &sfs);
+ r = statvfs(".", &svfs);
if (r == 0)
xr = get_xfer_size(t, -1, ".");
#endif
@@ -1918,14 +1918,14 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
- t->current_filesystem->xfer_align = sfs.f_frsize;
+ t->current_filesystem->xfer_align = svfs.f_frsize;
t->current_filesystem->max_xfer_size = -1;
- t->current_filesystem->min_xfer_size = sfs.f_bsize;
- t->current_filesystem->incr_xfer_size = sfs.f_bsize;
+ t->current_filesystem->min_xfer_size = svfs.f_bsize;
+ t->current_filesystem->incr_xfer_size = svfs.f_bsize;
}
#if defined(ST_NOATIME)
- if (sfs.f_flag & ST_NOATIME)
+ if (svfs.f_flag & ST_NOATIME)
t->current_filesystem->noatime = 1;
else
#endif
@@ -1933,7 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(USE_READDIR_R)
/* Set maximum filename length. */
- t->current_filesystem->name_max = sfs.f_namemax;
+ t->current_filesystem->name_max = svfs.f_namemax;
#endif
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_filter.3 b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
index 1ba5fcbd6..4f5c3518a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_filter.3
+++ b/Utilities/cmlibarchive/libarchive/archive_read_filter.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 14, 2014
+.Dd June 9, 2020
.Dt ARCHIVE_READ_FILTER 3
.Os
.Sh NAME
@@ -50,6 +50,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_read_support_filter_all "struct archive *"
.Ft int
+.Fn archive_read_support_filter_by_code "struct archive *" "int"
+.Ft int
.Fn archive_read_support_filter_bzip2 "struct archive *"
.Ft int
.Fn archive_read_support_filter_compress "struct archive *"
@@ -116,6 +118,14 @@ Note that
is always enabled by default.
.It Fn archive_read_support_filter_all
Enables all available decompression filters.
+.It Fn archive_read_support_filter_by_code
+Enables a single filter specified by the filter code.
+This function does not work with
+.Cm ARCHIVE_FILTER_PROGRAM .
+Note: In statically-linked executables, this will cause
+your program to include support for every filter.
+If executable size is a concern, you may wish to avoid
+using this function.
.It Fn archive_read_support_filter_program
Data is fed through the specified external program before being dearchived.
Note that this disables automatic detection of the compression format,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
index 86635e219..561289b69 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
@@ -221,7 +221,9 @@ file_open(struct archive *a, void *client_data)
struct read_file_data *mine = (struct read_file_data *)client_data;
void *buffer;
const char *filename = NULL;
+#if defined(_WIN32) && !defined(__CYGWIN__)
const wchar_t *wfilename = NULL;
+#endif
int fd = -1;
int is_disk_like = 0;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -281,10 +283,12 @@ file_open(struct archive *a, void *client_data)
#endif
}
if (fstat(fd, &st) != 0) {
+#if defined(_WIN32) && !defined(__CYGWIN__)
if (mine->filename_type == FNT_WCS)
archive_set_error(a, errno, "Can't stat '%S'",
wfilename);
else
+#endif
archive_set_error(a, errno, "Can't stat '%s'",
filename);
goto fail;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_set_format.c b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c
index 1d3e49d16..796dcdcce 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_set_format.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_set_format.c
@@ -61,6 +61,9 @@ archive_read_set_format(struct archive *_a, int code)
case ARCHIVE_FORMAT_CPIO:
strcpy(str, "cpio");
break;
+ case ARCHIVE_FORMAT_EMPTY:
+ strcpy(str, "empty");
+ break;
case ARCHIVE_FORMAT_ISO9660:
strcpy(str, "iso9660");
break;
@@ -76,9 +79,15 @@ archive_read_set_format(struct archive *_a, int code)
case ARCHIVE_FORMAT_RAR_V5:
strcpy(str, "rar5");
break;
+ case ARCHIVE_FORMAT_RAW:
+ strcpy(str, "raw");
+ break;
case ARCHIVE_FORMAT_TAR:
strcpy(str, "tar");
break;
+ case ARCHIVE_FORMAT_WARC:
+ strcpy(str, "warc");
+ break;
case ARCHIVE_FORMAT_XAR:
strcpy(str, "xar");
break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_by_code.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_by_code.c
new file mode 100644
index 000000000..94c4af695
--- /dev/null
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_by_code.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2020 Martin Matuska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include "archive.h"
+#include "archive_private.h"
+
+int
+archive_read_support_filter_by_code(struct archive *a, int filter_code)
+{
+ archive_check_magic(a, ARCHIVE_READ_MAGIC,
+ ARCHIVE_STATE_NEW, "archive_read_support_filter_by_code");
+
+ switch (filter_code) {
+ case ARCHIVE_FILTER_NONE:
+ return archive_read_support_filter_none(a);
+ break;
+ case ARCHIVE_FILTER_GZIP:
+ return archive_read_support_filter_gzip(a);
+ break;
+ case ARCHIVE_FILTER_BZIP2:
+ return archive_read_support_filter_bzip2(a);
+ break;
+ case ARCHIVE_FILTER_COMPRESS:
+ return archive_read_support_filter_compress(a);
+ break;
+ case ARCHIVE_FILTER_LZMA:
+ return archive_read_support_filter_lzma(a);
+ break;
+ case ARCHIVE_FILTER_XZ:
+ return archive_read_support_filter_xz(a);
+ break;
+ case ARCHIVE_FILTER_UU:
+ return archive_read_support_filter_uu(a);
+ break;
+ case ARCHIVE_FILTER_RPM:
+ return archive_read_support_filter_rpm(a);
+ break;
+ case ARCHIVE_FILTER_LZIP:
+ return archive_read_support_filter_lzip(a);
+ break;
+ case ARCHIVE_FILTER_LRZIP:
+ return archive_read_support_filter_lrzip(a);
+ break;
+ case ARCHIVE_FILTER_LZOP:
+ return archive_read_support_filter_lzop(a);
+ break;
+ case ARCHIVE_FILTER_GRZIP:
+ return archive_read_support_filter_grzip(a);
+ break;
+ case ARCHIVE_FILTER_LZ4:
+ return archive_read_support_filter_lz4(a);
+ break;
+ case ARCHIVE_FILTER_ZSTD:
+ return archive_read_support_filter_zstd(a);
+ break;
+ }
+ return (ARCHIVE_FATAL);
+}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
index b8bf12886..bf5b6f2b3 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_program.c
@@ -400,7 +400,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
static const size_t out_buf_len = 65536;
char *out_buf;
const char *prefix = "Program: ";
- pid_t child;
+ int ret;
size_t l;
l = strlen(prefix) + strlen(cmd) + 1;
@@ -426,9 +426,9 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
state->out_buf = out_buf;
state->out_buf_len = out_buf_len;
- child = __archive_create_child(cmd, &state->child_stdin,
- &state->child_stdout);
- if (child == -1) {
+ ret = __archive_create_child(cmd, &state->child_stdin,
+ &state->child_stdout, &state->child);
+ if (ret != ARCHIVE_OK) {
free(state->out_buf);
archive_string_free(&state->description);
free(state);
@@ -437,21 +437,6 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd)
cmd);
return (ARCHIVE_FATAL);
}
-#if defined(_WIN32) && !defined(__CYGWIN__)
- state->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
- if (state->child == NULL) {
- child_stop(self, state);
- free(state->out_buf);
- archive_string_free(&state->description);
- free(state);
- archive_set_error(&self->archive->archive, EINVAL,
- "Can't initialize filter; unable to run program \"%s\"",
- cmd);
- return (ARCHIVE_FATAL);
- }
-#else
- state->child = child;
-#endif
self->data = state;
self->read = program_filter_read;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c
index e1ec60e4e..c4e8ec7ec 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_zstd.c
@@ -119,6 +119,8 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
/* Zstd frame magic values */
const unsigned zstd_magic = 0xFD2FB528U;
+ const unsigned zstd_magic_skippable_start = 0x184D2A50U;
+ const unsigned zstd_magic_skippable_mask = 0xFFFFFFF0;
(void) self; /* UNUSED */
@@ -129,6 +131,8 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self,
prefix = archive_le32dec(buffer);
if (prefix == zstd_magic)
return (32);
+ if ((prefix & zstd_magic_skippable_mask) == zstd_magic_skippable_start)
+ return (32);
return (0);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_by_code.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_by_code.c
index 034353d78..89e96f1f5 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_by_code.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_by_code.c
@@ -26,6 +26,10 @@
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
#include "archive.h"
#include "archive_private.h"
@@ -48,6 +52,9 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
case ARCHIVE_FORMAT_CPIO:
return archive_read_support_format_cpio(a);
break;
+ case ARCHIVE_FORMAT_EMPTY:
+ return archive_read_support_format_empty(a);
+ break;
case ARCHIVE_FORMAT_ISO9660:
return archive_read_support_format_iso9660(a);
break;
@@ -63,9 +70,15 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
case ARCHIVE_FORMAT_RAR_V5:
return archive_read_support_format_rar5(a);
break;
+ case ARCHIVE_FORMAT_RAW:
+ return archive_read_support_format_raw(a);
+ break;
case ARCHIVE_FORMAT_TAR:
return archive_read_support_format_tar(a);
break;
+ case ARCHIVE_FORMAT_WARC:
+ return archive_read_support_format_warc(a);
+ break;
case ARCHIVE_FORMAT_XAR:
return archive_read_support_format_xar(a);
break;
@@ -73,5 +86,7 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
return archive_read_support_format_zip(a);
break;
}
+ archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
+ "Invalid format code specified");
return (ARCHIVE_FATAL);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
index 58644baf2..57547d496 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
@@ -1172,7 +1172,7 @@ cab_checksum_finish(struct archive_read *a)
cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated);
if (cfdata->sum_calculated != cfdata->sum) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Checksum error CFDATA[%d] %x:%x in %d bytes",
+ "Checksum error CFDATA[%d] %" PRIx32 ":%" PRIx32 " in %d bytes",
cab->entry_cffolder->cfdata_index -1,
cfdata->sum, cfdata->sum_calculated,
cfdata->compressed_size);
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
index c641eb9b1..53fb6cc47 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_empty.c
@@ -47,7 +47,7 @@ archive_read_support_format_empty(struct archive *_a)
r = __archive_read_register_format(a,
NULL,
- NULL,
+ "empty",
archive_read_format_empty_bid,
NULL,
archive_read_format_empty_read_header,
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
index 332944ac5..93ba2959a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#include "archive.h"
#include "archive_entry.h"
+#include "archive_entry_private.h"
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_read_private.h"
@@ -135,6 +136,9 @@ static int skip(struct archive_read *a);
static int read_header(struct archive_read *,
struct archive_entry *);
static int64_t mtree_atol(char **, int base);
+#ifndef HAVE_STRNLEN
+static size_t mtree_strnlen(const char *, size_t);
+#endif
/*
* There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them
@@ -186,6 +190,24 @@ get_time_t_min(void)
#endif
}
+#ifdef HAVE_STRNLEN
+#define mtree_strnlen(a,b) strnlen(a,b)
+#else
+static size_t
+mtree_strnlen(const char *p, size_t maxlen)
+{
+ size_t i;
+
+ for (i = 0; i <= maxlen; i++) {
+ if (p[i] == 0)
+ break;
+ }
+ if (i > maxlen)
+ return (-1);/* invalid */
+ return (i);
+}
+#endif
+
static int
archive_read_format_mtree_options(struct archive_read *a,
const char *key, const char *val)
@@ -1482,6 +1504,84 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
#undef MAX_PACK_ARGS
}
+static int
+parse_hex_nibble(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return 10 + c - 'a';
+#if 0
+ /* XXX: Is uppercase something we should support? */
+ if (c >= 'A' && c <= 'F')
+ return 10 + c - 'A';
+#endif
+
+ return -1;
+}
+
+static int
+parse_digest(struct archive_read *a, struct archive_entry *entry,
+ const char *digest, int type)
+{
+ unsigned char digest_buf[64];
+ int high, low;
+ size_t i, j, len;
+
+ switch (type) {
+ case ARCHIVE_ENTRY_DIGEST_MD5:
+ len = sizeof(entry->digest.md5);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_RMD160:
+ len = sizeof(entry->digest.rmd160);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA1:
+ len = sizeof(entry->digest.sha1);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA256:
+ len = sizeof(entry->digest.sha256);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA384:
+ len = sizeof(entry->digest.sha384);
+ break;
+ case ARCHIVE_ENTRY_DIGEST_SHA512:
+ len = sizeof(entry->digest.sha512);
+ break;
+ default:
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Unknown digest type");
+ return ARCHIVE_FATAL;
+ }
+
+ if (len > sizeof(digest_buf)) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Internal error: Digest storage too large");
+ return ARCHIVE_FATAL;
+ }
+
+ len *= 2;
+
+ if (mtree_strnlen(digest, len+1) != len) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "incorrect digest length, ignoring");
+ return ARCHIVE_WARN;
+ }
+
+ for (i = 0, j = 0; i < len; i += 2, j++) {
+ high = parse_hex_nibble(digest[i]);
+ low = parse_hex_nibble(digest[i+1]);
+ if (high == -1 || low == -1) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "invalid digest data, ignoring");
+ return ARCHIVE_WARN;
+ }
+
+ digest_buf[j] = high << 4 | low;
+ }
+
+ return archive_entry_set_digest(entry, type, digest_buf);
+}
+
/*
* Parse a single keyword and its value.
*/
@@ -1580,8 +1680,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
}
__LA_FALLTHROUGH;
case 'm':
- if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
- break;
+ if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_MD5);
+ }
if (strcmp(key, "mode") == 0) {
if (val[0] >= '0' && val[0] <= '7') {
*parsed_kws |= MTREE_HAS_PERM;
@@ -1617,21 +1719,32 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
return r;
}
if (strcmp(key, "rmd160") == 0 ||
- strcmp(key, "rmd160digest") == 0)
- break;
+ strcmp(key, "rmd160digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_RMD160);
+ }
__LA_FALLTHROUGH;
case 's':
- if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
- break;
+ if (strcmp(key, "sha1") == 0 ||
+ strcmp(key, "sha1digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_SHA1);
+ }
if (strcmp(key, "sha256") == 0 ||
- strcmp(key, "sha256digest") == 0)
- break;
+ strcmp(key, "sha256digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_SHA256);
+ }
if (strcmp(key, "sha384") == 0 ||
- strcmp(key, "sha384digest") == 0)
- break;
+ strcmp(key, "sha384digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_SHA384);
+ }
if (strcmp(key, "sha512") == 0 ||
- strcmp(key, "sha512digest") == 0)
- break;
+ strcmp(key, "sha512digest") == 0) {
+ return parse_digest(a, entry, val,
+ ARCHIVE_ENTRY_DIGEST_SHA512);
+ }
if (strcmp(key, "size") == 0) {
archive_entry_set_size(entry, mtree_atol(&val, 10));
break;
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
index 61f233085..6dca350c9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
@@ -151,6 +151,9 @@
#undef minimum
#define minimum(a, b) ((a)<(b)?(a):(b))
+/* Stack overflow check */
+#define MAX_COMPRESS_DEPTH 1024
+
/* Fields common to all headers */
struct rar_header
{
@@ -340,7 +343,7 @@ static int read_symlink_stored(struct archive_read *, struct archive_entry *,
static int read_data_stored(struct archive_read *, const void **, size_t *,
int64_t *);
static int read_data_compressed(struct archive_read *, const void **, size_t *,
- int64_t *);
+ int64_t *, size_t);
static int rar_br_preparation(struct archive_read *, struct rar_br *);
static int parse_codes(struct archive_read *);
static void free_codes(struct archive_read *);
@@ -1026,7 +1029,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
case COMPRESS_METHOD_NORMAL:
case COMPRESS_METHOD_GOOD:
case COMPRESS_METHOD_BEST:
- ret = read_data_compressed(a, buff, size, offset);
+ ret = read_data_compressed(a, buff, size, offset, 0);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
rar->start_new_table = 1;
@@ -1883,8 +1886,11 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
static int
read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
- int64_t *offset)
+ int64_t *offset, size_t looper)
{
+ if (looper++ > MAX_COMPRESS_DEPTH)
+ return (ARCHIVE_FATAL);
+
struct rar *rar;
int64_t start, end, actualend;
size_t bs;
@@ -1982,7 +1988,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
{
case 0:
rar->start_new_table = 1;
- return read_data_compressed(a, buff, size, offset);
+ return read_data_compressed(a, buff, size, offset, looper);
case 2:
rar->ppmd_eod = 1;/* End Of ppmd Data. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
index d3a1c1b2c..31319553a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar5.c
@@ -3084,12 +3084,6 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
continue;
}
-
- /* The program counter shouldn't reach here. */
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported block code: 0x%x", num);
-
- return ARCHIVE_FATAL;
}
return ARCHIVE_OK;
@@ -3837,7 +3831,7 @@ static int verify_checksums(struct archive_read* a) {
DEBUG_CODE {
printf("Checksum error: CRC32 "
- "(was: %08x, expected: %08x)\n",
+ "(was: %08" PRIx32 ", expected: %08" PRIx32 ")\n",
rar->file.calculated_crc32,
rar->file.stored_crc32);
}
@@ -3851,7 +3845,7 @@ static int verify_checksums(struct archive_read* a) {
} else {
DEBUG_CODE {
printf("Checksum OK: CRC32 "
- "(%08x/%08x)\n",
+ "(%08" PRIx32 "/%08" PRIx32 ")\n",
rar->file.stored_crc32,
rar->file.calculated_crc32);
}
@@ -3912,6 +3906,9 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
int ret;
struct rar5* rar = get_context(a);
+ if (size)
+ *size = 0;
+
if(rar->file.dir > 0) {
/* Don't process any data if this file entry was declared
* as a directory. This is needed, because entries marked as
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
index c63d46fc0..96d810184 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
@@ -1797,6 +1797,16 @@ pax_attribute_schily_xattr(struct archive_entry *entry,
}
static int
+pax_attribute_rht_security_selinux(struct archive_entry *entry,
+ const char *value, size_t value_length)
+{
+ archive_entry_xattr_add_entry(entry, "security.selinux",
+ value, value_length);
+
+ return 0;
+}
+
+static int
pax_attribute_acl(struct archive_read *a, struct tar *tar,
struct archive_entry *entry, const char *value, int type)
{
@@ -1966,6 +1976,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0)
pax_attribute_xattr(entry, key, value);
break;
+ case 'R':
+ /* GNU tar uses RHT.security header to store SELinux xattrs
+ * SCHILY.xattr.security.selinux == RHT.security.selinux */
+ if (strcmp(key, "RHT.security.selinux") == 0) {
+ pax_attribute_rht_security_selinux(entry, value,
+ value_length);
+ }
+ break;
case 'S':
/* We support some keys used by the "star" archiver */
if (strcmp(key, "SCHILY.acl.access") == 0) {
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
index 72977b8e0..27329962d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c
@@ -127,7 +127,7 @@ static int _warc_skip(struct archive_read *a);
static int _warc_rdhdr(struct archive_read *a, struct archive_entry *e);
/* private routines */
-static unsigned int _warc_rdver(const char buf[10], size_t bsz);
+static unsigned int _warc_rdver(const char *buf, size_t bsz);
static unsigned int _warc_rdtyp(const char *buf, size_t bsz);
static warc_string_t _warc_rduri(const char *buf, size_t bsz);
static ssize_t _warc_rdlen(const char *buf, size_t bsz);
@@ -337,6 +337,14 @@ start_over:
mtime = rtime;
}
break;
+ case WT_NONE:
+ case WT_INFO:
+ case WT_META:
+ case WT_REQ:
+ case WT_RVIS:
+ case WT_CONV:
+ case WT_CONT:
+ case LAST_WT:
default:
fnam.len = 0U;
fnam.str = NULL;
@@ -361,6 +369,14 @@ start_over:
break;
}
/* FALLTHROUGH */
+ case WT_NONE:
+ case WT_INFO:
+ case WT_META:
+ case WT_REQ:
+ case WT_RVIS:
+ case WT_CONV:
+ case WT_CONT:
+ case LAST_WT:
default:
/* consume the content and start over */
_warc_skip(a);
@@ -427,7 +443,7 @@ _warc_skip(struct archive_read *a)
static void*
deconst(const void *c)
{
- return (char *)0x1 + (((const char *)c) - (const char *)0x1);
+ return (void *)(uintptr_t)c;
}
static char*
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
index 9489e5106..2e60cf721 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
@@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$");
#elif HAVE_BSDXML_H
#include <bsdxml.h>
#elif HAVE_EXPAT_H
-#include <expat.h>
+#include <cm3p/expat.h>
#endif
#ifdef HAVE_BZLIB_H
#include <cm3p/bzlib.h>
@@ -458,6 +458,11 @@ archive_read_support_format_xar(struct archive *_a)
return (ARCHIVE_FATAL);
}
+ /* initialize xar->file_queue */
+ xar->file_queue.allocated = 0;
+ xar->file_queue.used = 0;
+ xar->file_queue.files = NULL;
+
r = __archive_read_register_format(a,
xar,
"xar",
@@ -1221,10 +1226,12 @@ heap_add_entry(struct archive_read *a,
/* Expand our pending files list as necessary. */
if (heap->used >= heap->allocated) {
struct xar_file **new_pending_files;
- int new_size = heap->allocated * 2;
+ int new_size;
if (heap->allocated < 1024)
new_size = 1024;
+ else
+ new_size = heap->allocated * 2;
/* Overflow might keep us from growing the list. */
if (new_size <= heap->allocated) {
archive_set_error(&a->archive,
@@ -1238,9 +1245,11 @@ heap_add_entry(struct archive_read *a,
ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
- memcpy(new_pending_files, heap->files,
- heap->allocated * sizeof(new_pending_files[0]));
- free(heap->files);
+ if (heap->allocated) {
+ memcpy(new_pending_files, heap->files,
+ heap->allocated * sizeof(new_pending_files[0]));
+ free(heap->files);
+ }
heap->files = new_pending_files;
heap->allocated = new_size;
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
index 4d71f985a..6314c68a4 100644
--- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c
@@ -53,10 +53,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102
#include <cm3p/zlib.h>
#endif
#ifdef HAVE_BZLIB_H
-#include <bzlib.h>
+#include <cm3p/bzlib.h>
#endif
#ifdef HAVE_LZMA_H
-#include <lzma.h>
+#include <cm3p/lzma.h>
#endif
#include "archive.h"
@@ -899,6 +899,81 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
return ARCHIVE_OK;
}
+#if HAVE_LZMA_H && HAVE_LIBLZMA
+/*
+ * Auxiliary function to uncompress data chunk from zipx archive
+ * (zip with lzma compression).
+ */
+static int
+zipx_lzma_uncompress_buffer(const char *compressed_buffer,
+ size_t compressed_buffer_size,
+ char *uncompressed_buffer,
+ size_t uncompressed_buffer_size)
+{
+ int status = ARCHIVE_FATAL;
+ // length of 'lzma properties data' in lzma compressed
+ // data segment (stream) inside zip archive
+ const size_t lzma_params_length = 5;
+ // offset of 'lzma properties data' from the beginning of lzma stream
+ const size_t lzma_params_offset = 4;
+ // end position of 'lzma properties data' in lzma stream
+ const size_t lzma_params_end = lzma_params_offset + lzma_params_length;
+ if (compressed_buffer == NULL ||
+ compressed_buffer_size < lzma_params_end ||
+ uncompressed_buffer == NULL)
+ return status;
+
+ // prepare header for lzma_alone_decoder to replace zipx header
+ // (see comments in 'zipx_lzma_alone_init' for justification)
+#pragma pack(push)
+#pragma pack(1)
+ struct _alone_header
+ {
+ uint8_t bytes[5]; // lzma_params_length
+ uint64_t uncompressed_size;
+ } alone_header;
+#pragma pack(pop)
+ // copy 'lzma properties data' blob
+ memcpy(&alone_header.bytes[0], compressed_buffer + lzma_params_offset,
+ lzma_params_length);
+ alone_header.uncompressed_size = UINT64_MAX;
+
+ // prepare new compressed buffer, see 'zipx_lzma_alone_init' for details
+ const size_t lzma_alone_buffer_size =
+ compressed_buffer_size - lzma_params_end + sizeof(alone_header);
+ unsigned char *lzma_alone_compressed_buffer =
+ (unsigned char*) malloc(lzma_alone_buffer_size);
+ if (lzma_alone_compressed_buffer == NULL)
+ return status;
+ // copy lzma_alone header into new buffer
+ memcpy(lzma_alone_compressed_buffer, (void*) &alone_header,
+ sizeof(alone_header));
+ // copy compressed data into new buffer
+ memcpy(lzma_alone_compressed_buffer + sizeof(alone_header),
+ compressed_buffer + lzma_params_end,
+ compressed_buffer_size - lzma_params_end);
+
+ // create and fill in lzma_alone_decoder stream
+ lzma_stream stream = LZMA_STREAM_INIT;
+ lzma_ret ret = lzma_alone_decoder(&stream, UINT64_MAX);
+ if (ret == LZMA_OK)
+ {
+ stream.next_in = lzma_alone_compressed_buffer;
+ stream.avail_in = lzma_alone_buffer_size;
+ stream.total_in = 0;
+ stream.next_out = (unsigned char*)uncompressed_buffer;
+ stream.avail_out = uncompressed_buffer_size;
+ stream.total_out = 0;
+ ret = lzma_code(&stream, LZMA_RUN);
+ if (ret == LZMA_OK || ret == LZMA_STREAM_END)
+ status = ARCHIVE_OK;
+ }
+ lzma_end(&stream);
+ free(lzma_alone_compressed_buffer);
+ return status;
+}
+#endif
+
/*
* Assumes file pointer is at beginning of local file header.
*/
@@ -1173,18 +1248,64 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
"Truncated Zip file");
return ARCHIVE_FATAL;
}
+ // take into account link compression if any
+ size_t linkname_full_length = linkname_length;
+ if (zip->entry->compression != 0)
+ {
+ // symlink target string appeared to be compressed
+ int status = ARCHIVE_FATAL;
+ char *uncompressed_buffer =
+ (char*) malloc(zip_entry->uncompressed_size);
+ if (uncompressed_buffer == NULL)
+ {
+ archive_set_error(&a->archive, ENOMEM,
+ "No memory for lzma decompression");
+ return status;
+ }
+
+ switch (zip->entry->compression)
+ {
+#if HAVE_LZMA_H && HAVE_LIBLZMA
+ case 14: /* ZIPx LZMA compression. */
+ /*(see zip file format specification, section 4.4.5)*/
+ status = zipx_lzma_uncompress_buffer(p,
+ linkname_length,
+ uncompressed_buffer,
+ (size_t)zip_entry->uncompressed_size);
+ break;
+#endif
+ default: /* Unsupported compression. */
+ break;
+ }
+ if (status == ARCHIVE_OK)
+ {
+ p = uncompressed_buffer;
+ linkname_full_length =
+ (size_t)zip_entry->uncompressed_size;
+ }
+ else
+ {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unsupported ZIP compression method "
+ "during decompression of link entry (%d: %s)",
+ zip->entry->compression,
+ compression_name(zip->entry->compression));
+ return ARCHIVE_FAILED;
+ }
+ }
sconv = zip->sconv;
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
sconv = zip->sconv_utf8;
if (sconv == NULL)
sconv = zip->sconv_default;
- if (archive_entry_copy_symlink_l(entry, p, linkname_length,
+ if (archive_entry_copy_symlink_l(entry, p, linkname_full_length,
sconv) != 0) {
if (errno != ENOMEM && sconv == zip->sconv_utf8 &&
(zip->entry->zip_flags & ZIP_UTF8_NAME))
archive_entry_copy_symlink_l(entry, p,
- linkname_length, NULL);
+ linkname_full_length, NULL);
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory for Symlink");
@@ -1901,15 +2022,15 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
if(order < 2 || restore_method > 2) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Invalid parameter set in PPMd8 stream (order=%d, "
- "restore=%d)", order, restore_method);
+ "Invalid parameter set in PPMd8 stream (order=%" PRId32 ", "
+ "restore=%" PRId32 ")", order, restore_method);
return (ARCHIVE_FAILED);
}
/* Allocate the memory needed to properly decompress the file. */
if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) {
archive_set_error(&a->archive, ENOMEM,
- "Unable to allocate memory for PPMd8 stream: %d bytes",
+ "Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes",
mem << 20);
return (ARCHIVE_FATAL);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c
index c77dcf52c..7460ded00 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.c
+++ b/Utilities/cmlibarchive/libarchive/archive_string.c
@@ -3881,6 +3881,11 @@ archive_mstring_get_utf8(struct archive *a, struct archive_mstring *aes,
}
*p = NULL;
+ /* Try converting WCS to MBS first if MBS does not exist yet. */
+ if ((aes->aes_set & AES_SET_MBS) == 0) {
+ const char *pm; /* unused */
+ archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */
+ }
if (aes->aes_set & AES_SET_MBS) {
sc = archive_string_conversion_to_charset(a, "UTF-8", 1);
if (sc == NULL)
@@ -3903,9 +3908,9 @@ int
archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes,
const char **p)
{
+ struct archive_string_conv *sc;
int r, ret = 0;
- (void)a; /* UNUSED */
/* If we already have an MBS form, return that immediately. */
if (aes->aes_set & AES_SET_MBS) {
*p = aes->aes_mbs.s;
@@ -3926,10 +3931,23 @@ archive_mstring_get_mbs(struct archive *a, struct archive_mstring *aes,
ret = -1;
}
- /*
- * Only a UTF-8 form cannot avail because its conversion already
- * failed at archive_mstring_update_utf8().
- */
+ /* If there's a UTF-8 form, try converting with the native locale. */
+ if (aes->aes_set & AES_SET_UTF8) {
+ archive_string_empty(&(aes->aes_mbs));
+ sc = archive_string_conversion_from_charset(a, "UTF-8", 1);
+ if (sc == NULL)
+ return (-1);/* Couldn't allocate memory for sc. */
+ r = archive_strncpy_l(&(aes->aes_mbs),
+ aes->aes_utf8.s, aes->aes_utf8.length, sc);
+ if (a == NULL)
+ free_sconv_object(sc);
+ *p = aes->aes_mbs.s;
+ if (r == 0) {
+ aes->aes_set |= AES_SET_MBS;
+ ret = 0;/* success; overwrite previous error. */
+ } else
+ ret = -1;/* failure. */
+ }
return (ret);
}
@@ -3947,6 +3965,11 @@ archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes,
}
*wp = NULL;
+ /* Try converting UTF8 to MBS first if MBS does not exist yet. */
+ if ((aes->aes_set & AES_SET_MBS) == 0) {
+ const char *p; /* unused */
+ archive_mstring_get_mbs(a, aes, &p); /* ignore errors, we'll handle it later */
+ }
/* Try converting MBS to WCS using native locale. */
if (aes->aes_set & AES_SET_MBS) {
archive_wstring_empty(&(aes->aes_wcs));
@@ -3962,11 +3985,12 @@ archive_mstring_get_wcs(struct archive *a, struct archive_mstring *aes,
}
int
-archive_mstring_get_mbs_l(struct archive_mstring *aes,
+archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
const char **p, size_t *length, struct archive_string_conv *sc)
{
int r, ret = 0;
+ (void)r; /* UNUSED */
#if defined(_WIN32) && !defined(__CYGWIN__)
/*
* Internationalization programming on Windows must use Wide
@@ -3989,20 +4013,12 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes,
}
#endif
- /* If there is not an MBS form but is a WCS form, try converting
+ /* If there is not an MBS form but there is a WCS or UTF8 form, try converting
* with the native locale to be used for translating it to specified
* character-set. */
- if ((aes->aes_set & AES_SET_MBS) == 0 &&
- (aes->aes_set & AES_SET_WCS) != 0) {
- archive_string_empty(&(aes->aes_mbs));
- r = archive_string_append_from_wcs(&(aes->aes_mbs),
- aes->aes_wcs.s, aes->aes_wcs.length);
- if (r == 0)
- aes->aes_set |= AES_SET_MBS;
- else if (errno == ENOMEM)
- return (-1);
- else
- ret = -1;
+ if ((aes->aes_set & AES_SET_MBS) == 0) {
+ const char *pm; /* unused */
+ archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */
}
/* If we already have an MBS form, use it to be translated to
* specified character-set. */
diff --git a/Utilities/cmlibarchive/libarchive/archive_string.h b/Utilities/cmlibarchive/libarchive/archive_string.h
index 27e1ad69c..49d7d3064 100644
--- a/Utilities/cmlibarchive/libarchive/archive_string.h
+++ b/Utilities/cmlibarchive/libarchive/archive_string.h
@@ -226,7 +226,7 @@ void archive_mstring_copy(struct archive_mstring *dest, struct archive_mstring *
int archive_mstring_get_mbs(struct archive *, struct archive_mstring *, const char **);
int archive_mstring_get_utf8(struct archive *, struct archive_mstring *, const char **);
int archive_mstring_get_wcs(struct archive *, struct archive_mstring *, const wchar_t **);
-int archive_mstring_get_mbs_l(struct archive_mstring *, const char **,
+int archive_mstring_get_mbs_l(struct archive *, struct archive_mstring *, const char **,
size_t *, struct archive_string_conv *);
int archive_mstring_copy_mbs(struct archive_mstring *, const char *mbs);
int archive_mstring_copy_mbs_len(struct archive_mstring *, const char *mbs,
diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c
index 10dca73c6..83586b5e9 100644
--- a/Utilities/cmlibarchive/libarchive/archive_util.c
+++ b/Utilities/cmlibarchive/libarchive/archive_util.c
@@ -365,6 +365,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
}
fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR);
if (fd == -1) {
+ la_dosmaperr(GetLastError());
CloseHandle(h);
goto exit_tmpfile;
} else
@@ -432,6 +433,11 @@ __archive_mktemp(const char *tmpdir)
if (temp_name.s[temp_name.length-1] != '/')
archive_strappend_char(&temp_name, '/');
}
+#ifdef O_TMPFILE
+ fd = open(temp_name.s, O_RDWR|O_CLOEXEC|O_TMPFILE|O_EXCL, 0600);
+ if(fd >= 0)
+ goto exit_tmpfile;
+#endif
archive_strcat(&temp_name, "libarchive_XXXXXX");
fd = mkstemp(temp_name.s);
if (fd < 0)
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index 98a55fb2a..8d70f51a6 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -456,6 +456,25 @@ archive_write_client_write(struct archive_write_filter *f,
}
static int
+archive_write_client_free(struct archive_write_filter *f)
+{
+ struct archive_write *a = (struct archive_write *)f->archive;
+
+ if (a->client_freer)
+ (*a->client_freer)(&a->archive, a->client_data);
+ a->client_data = NULL;
+
+ /* Clear passphrase. */
+ if (a->passphrase != NULL) {
+ memset(a->passphrase, 0, strlen(a->passphrase));
+ free(a->passphrase);
+ a->passphrase = NULL;
+ }
+
+ return (ARCHIVE_OK);
+}
+
+static int
archive_write_client_close(struct archive_write_filter *f)
{
struct archive_write *a = (struct archive_write *)f->archive;
@@ -493,13 +512,7 @@ archive_write_client_close(struct archive_write_filter *f)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
free(state);
- a->client_data = NULL;
- /* Clear passphrase. */
- if (a->passphrase != NULL) {
- memset(a->passphrase, 0, strlen(a->passphrase));
- free(a->passphrase);
- a->passphrase = NULL;
- }
+
/* Clear the close handler myself not to be called again. */
f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
return (ret);
@@ -509,9 +522,9 @@ archive_write_client_close(struct archive_write_filter *f)
* Open the archive using the current settings.
*/
int
-archive_write_open(struct archive *_a, void *client_data,
+archive_write_open2(struct archive *_a, void *client_data,
archive_open_callback *opener, archive_write_callback *writer,
- archive_close_callback *closer)
+ archive_close_callback *closer, archive_free_callback *freer)
{
struct archive_write *a = (struct archive_write *)_a;
struct archive_write_filter *client_filter;
@@ -524,12 +537,14 @@ archive_write_open(struct archive *_a, void *client_data,
a->client_writer = writer;
a->client_opener = opener;
a->client_closer = closer;
+ a->client_freer = freer;
a->client_data = client_data;
client_filter = __archive_write_allocate_filter(_a);
client_filter->open = archive_write_client_open;
client_filter->write = archive_write_client_write;
client_filter->close = archive_write_client_close;
+ client_filter->free = archive_write_client_free;
ret = __archive_write_filters_open(a);
if (ret < ARCHIVE_WARN) {
@@ -544,6 +559,15 @@ archive_write_open(struct archive *_a, void *client_data,
return (ret);
}
+int
+archive_write_open(struct archive *_a, void *client_data,
+ archive_open_callback *opener, archive_write_callback *writer,
+ archive_close_callback *closer)
+{
+ return archive_write_open2(_a, client_data, opener, writer,
+ closer, NULL);
+}
+
/*
* Close out the archive.
*/
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
index a4bc1d90e..c096e7227 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c
@@ -196,10 +196,6 @@ __archive_write_program_free(struct archive_write_program_data *data)
{
if (data) {
-#if defined(_WIN32) && !defined(__CYGWIN__)
- if (data->child)
- CloseHandle(data->child);
-#endif
free(data->program_name);
free(data->child_buf);
free(data);
@@ -211,7 +207,7 @@ int
__archive_write_program_open(struct archive_write_filter *f,
struct archive_write_program_data *data, const char *cmd)
{
- pid_t child;
+ int ret;
if (data->child_buf == NULL) {
data->child_buf_len = 65536;
@@ -225,27 +221,13 @@ __archive_write_program_open(struct archive_write_filter *f,
}
}
- child = __archive_create_child(cmd, &data->child_stdin,
- &data->child_stdout);
- if (child == -1) {
+ ret = __archive_create_child(cmd, &data->child_stdin,
+ &data->child_stdout, &data->child);
+ if (ret != ARCHIVE_OK) {
archive_set_error(f->archive, EINVAL,
"Can't launch external program: %s", cmd);
return (ARCHIVE_FATAL);
}
-#if defined(_WIN32) && !defined(__CYGWIN__)
- data->child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, child);
- if (data->child == NULL) {
- close(data->child_stdin);
- data->child_stdin = -1;
- close(data->child_stdout);
- data->child_stdout = -1;
- archive_set_error(f->archive, EINVAL,
- "Can't launch external program: %s", cmd);
- return (ARCHIVE_FATAL);
- }
-#else
- data->child = child;
-#endif
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
index d567ac995..00df8da5a 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c
@@ -382,8 +382,12 @@ archive_compressor_xz_options(struct archive_write_filter *f,
value[1] != '\0')
return (ARCHIVE_WARN);
data->compression_level = value[0] - '0';
+ if (data->compression_level > 9)
+ data->compression_level = 9;
+#ifdef _AIX
if (data->compression_level > 6)
data->compression_level = 6;
+#endif
return (ARCHIVE_OK);
} else if (strcmp(key, "threads") == 0) {
char *endptr;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c
index f67b0256d..6d71628d2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_zstd.c
@@ -59,6 +59,16 @@ struct private_data {
#endif
};
+/* If we don't have the library use default range values (zstdcli.c v1.4.0) */
+#define CLEVEL_MIN -99
+#define CLEVEL_STD_MIN 0 /* prior to 1.3.4 and more recent without using --fast */
+#define CLEVEL_DEFAULT 3
+#define CLEVEL_STD_MAX 19 /* without using --ultra */
+#define CLEVEL_MAX 22
+
+#define MINVER_NEGCLEVEL 10304
+#define MINVER_MINCLEVEL 10306
+
static int archive_compressor_zstd_options(struct archive_write_filter *,
const char *, const char *);
static int archive_compressor_zstd_open(struct archive_write_filter *);
@@ -96,7 +106,7 @@ archive_write_add_filter_zstd(struct archive *_a)
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
f->name = "zstd";
- data->compression_level = 3; /* Default level used by the zstd CLI */
+ data->compression_level = CLEVEL_DEFAULT;
#if HAVE_ZSTD_H && HAVE_LIBZSTD
data->cstream = ZSTD_createCStream();
if (data->cstream == NULL) {
@@ -135,6 +145,31 @@ archive_compressor_zstd_free(struct archive_write_filter *f)
return (ARCHIVE_OK);
}
+static int string_is_numeric (const char* value)
+{
+ size_t len = strlen(value);
+ size_t i;
+
+ if (len == 0) {
+ return (ARCHIVE_WARN);
+ }
+ else if (len == 1 && !(value[0] >= '0' && value[0] <= '9')) {
+ return (ARCHIVE_WARN);
+ }
+ else if (!(value[0] >= '0' && value[0] <= '9') &&
+ value[0] != '-' && value[0] != '+') {
+ return (ARCHIVE_WARN);
+ }
+
+ for (i = 1; i < len; i++) {
+ if (!(value[i] >= '0' && value[i] <= '9')) {
+ return (ARCHIVE_WARN);
+ }
+ }
+
+ return (ARCHIVE_OK);
+}
+
/*
* Set write options.
*/
@@ -146,12 +181,25 @@ archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
if (strcmp(key, "compression-level") == 0) {
int level = atoi(value);
-#if HAVE_ZSTD_H && HAVE_LIBZSTD
- if (level < 1 || level > ZSTD_maxCLevel()) {
-#else
/* If we don't have the library, hard-code the max level */
- if (level < 1 || level > 22) {
+ int minimum = CLEVEL_MIN;
+ int maximum = CLEVEL_MAX;
+ if (string_is_numeric(value) != ARCHIVE_OK) {
+ return (ARCHIVE_WARN);
+ }
+#if HAVE_ZSTD_H && HAVE_LIBZSTD
+ maximum = ZSTD_maxCLevel();
+#if ZSTD_VERSION_NUMBER >= MINVER_MINCLEVEL
+ if (ZSTD_versionNumber() >= MINVER_MINCLEVEL) {
+ minimum = ZSTD_minCLevel();
+ }
+ else
+#endif
+ if (ZSTD_versionNumber() < MINVER_NEGCLEVEL) {
+ minimum = CLEVEL_STD_MIN;
+ }
#endif
+ if (level < minimum || level > maximum) {
return (ARCHIVE_WARN);
}
data->compression_level = level;
@@ -297,7 +345,26 @@ archive_compressor_zstd_open(struct archive_write_filter *f)
int r;
archive_string_init(&as);
- archive_string_sprintf(&as, "zstd -%d", data->compression_level);
+ /* --no-check matches library default */
+ archive_strcpy(&as, "zstd --no-check");
+
+ if (data->compression_level < CLEVEL_STD_MIN) {
+ struct archive_string as2;
+ archive_string_init(&as2);
+ archive_string_sprintf(&as2, " --fast=%d", -data->compression_level);
+ archive_string_concat(&as, &as2);
+ archive_string_free(&as2);
+ } else {
+ struct archive_string as2;
+ archive_string_init(&as2);
+ archive_string_sprintf(&as2, " -%d", data->compression_level);
+ archive_string_concat(&as, &as2);
+ archive_string_free(&as2);
+ }
+
+ if (data->compression_level > CLEVEL_STD_MAX) {
+ archive_strcat(&as, " --ultra");
+ }
f->write = archive_compressor_zstd_write;
r = __archive_write_program_open(f, data->pdata, as.s);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
index c4be9b0b2..2551ebef1 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c
@@ -546,6 +546,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
{
struct archive_write_disk *a = (struct archive_write_disk *)_a;
struct fixup_entry *fe;
+ const char *linkname;
int ret, r;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
@@ -591,6 +592,17 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
return (ret);
/*
+ * Check if we have a hardlink that points to itself.
+ */
+ linkname = archive_entry_hardlink(a->entry);
+ if (linkname != NULL && strcmp(a->name, linkname) == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Skipping hardlink pointing to itself: %s",
+ a->name);
+ return (ARCHIVE_WARN);
+ }
+
+ /*
* Query the umask so we get predictable mode settings.
* This gets done on every call to _write_header in case the
* user edits their umask during the extraction for some
@@ -1856,8 +1868,9 @@ finish_metadata:
if (a->tmpname) {
if (rename(a->tmpname, a->name) == -1) {
archive_set_error(&a->archive, errno,
- "rename failed");
- ret = ARCHIVE_FATAL;
+ "Failed to rename temporary file");
+ ret = ARCHIVE_FAILED;
+ unlink(a->tmpname);
}
a->tmpname = NULL;
}
@@ -2144,8 +2157,11 @@ restore_entry(struct archive_write_disk *a)
if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
S_ISREG(a->st.st_mode)) {
/* Use a temporary file to extract */
- if ((a->fd = la_mktemp(a)) == -1)
+ if ((a->fd = la_mktemp(a)) == -1) {
+ archive_set_error(&a->archive, errno,
+ "Can't create temporary file");
return ARCHIVE_FAILED;
+ }
a->pst = NULL;
en = 0;
} else {
@@ -4407,10 +4423,19 @@ set_xattrs(struct archive_write_disk *a)
int e;
int namespace;
+ namespace = EXTATTR_NAMESPACE_USER;
+
if (strncmp(name, "user.", 5) == 0) {
/* "user." attributes go to user namespace */
name += 5;
namespace = EXTATTR_NAMESPACE_USER;
+ } else if (strncmp(name, "system.", 7) == 0) {
+ name += 7;
+ namespace = EXTATTR_NAMESPACE_SYSTEM;
+ if (!strcmp(name, "nfs4.acl") ||
+ !strcmp(name, "posix1e.acl_access") ||
+ !strcmp(name, "posix1e.acl_default"))
+ continue;
} else {
/* Other namespaces are unsupported */
archive_strcat(&errlist, name);
@@ -4421,8 +4446,29 @@ set_xattrs(struct archive_write_disk *a)
}
if (a->fd >= 0) {
+ /*
+ * On FreeBSD, extattr_set_fd does not
+ * return the same as
+ * extattr_set_file. It returns zero
+ * on success, non-zero on failure.
+ *
+ * We can detect the failure by
+ * manually setting errno prior to the
+ * call and checking after.
+ *
+ * If errno remains zero, fake the
+ * return value by setting e to size.
+ *
+ * This is a hack for now until I
+ * (Shawn Webb) get FreeBSD to fix the
+ * issue, if that's even possible.
+ */
+ errno = 0;
e = extattr_set_fd(a->fd, namespace, name,
value, size);
+ if (e == 0 && errno == 0) {
+ e = size;
+ }
} else {
e = extattr_set_link(
archive_entry_pathname(entry), namespace,
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index 77e36c4a6..0c600176c 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -549,6 +549,8 @@ la_mktemp(struct archive_write_disk *a)
a->tmpname = a->_tmpname_data.s;
fd = __archive_mkstemp(a->tmpname);
+ if (fd == -1)
+ return -1;
mode = a->mode & 0777 & ~a->user_umask;
if (la_chmod(a->tmpname, mode) == -1) {
@@ -1281,9 +1283,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
/* Windows does not support atomic rename */
disk_unlink(a->name);
if (_wrename(a->tmpname, a->name) != 0) {
+ la_dosmaperr(GetLastError());
archive_set_error(&a->archive, errno,
- "rename failed");
- ret = ARCHIVE_FATAL;
+ "Failed to rename temporary file");
+ ret = ARCHIVE_FAILED;
+ disk_unlink(a->tmpname);
}
a->tmpname = NULL;
}
@@ -1573,12 +1577,17 @@ restore_entry(struct archive_write_disk *a)
S_ISREG(st_mode)) {
int fd = la_mktemp(a);
- if (fd == -1)
+ if (fd == -1) {
+ la_dosmaperr(GetLastError());
+ archive_set_error(&a->archive, errno,
+ "Can't create temporary file");
return (ARCHIVE_FAILED);
+ }
a->fh = (HANDLE)_get_osfhandle(fd);
- if (a->fh == INVALID_HANDLE_VALUE)
+ if (a->fh == INVALID_HANDLE_VALUE) {
+ la_dosmaperr(GetLastError());
return (ARCHIVE_FAILED);
-
+ }
a->pst = NULL;
en = 0;
} else {
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open.3 b/Utilities/cmlibarchive/libarchive/archive_write_open.3
index 0129d10b7..29bffe49e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open.3
@@ -24,11 +24,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 2, 2012
+.Dd November 12, 2020
.Dt ARCHIVE_WRITE_OPEN 3
.Os
.Sh NAME
.Nm archive_write_open ,
+.Nm archive_write_open2 ,
.Nm archive_write_open_fd ,
.Nm archive_write_open_FILE ,
.Nm archive_write_open_filename ,
@@ -47,6 +48,15 @@ Streaming Archive Library (libarchive, -larchive)
.Fa "archive_close_callback *"
.Fc
.Ft int
+.Fo archive_write_open2
+.Fa "struct archive *"
+.Fa "void *client_data"
+.Fa "archive_open_callback *"
+.Fa "archive_write_callback *"
+.Fa "archive_close_callback *"
+.Fa "archive_free_callback *"
+.Fc
+.Ft int
.Fn archive_write_open_fd "struct archive *" "int fd"
.Ft int
.Fn archive_write_open_FILE "struct archive *" "FILE *file"
@@ -67,6 +77,11 @@ This is the most generic form of this function, which accepts
pointers to three callback functions which will be invoked by
the compression layer to write the constructed archive.
This does not alter the default archive padding.
+.It Fn archive_write_open2
+Same as
+.Fn archive_write_open
+with an additional fourth free callback. This function should be preferred to
+.Fn archive_write_open .
.It Fn archive_write_open_fd
A convenience form of
.Fn archive_write_open
@@ -106,14 +121,14 @@ to a character or block device node, it will disable padding otherwise.
You can override this by manually invoking
.Fn archive_write_set_bytes_in_last_block
before calling
-.Fn archive_write_open .
+.Fn archive_write_open2 .
The
.Fn archive_write_open_filename
function is safe for use with tape drives or other
block-oriented devices.
.It Fn archive_write_open_memory
A convenience form of
-.Fn archive_write_open
+.Fn archive_write_open2
that accepts a pointer to a block of memory that will receive
the archive.
The final
@@ -145,7 +160,7 @@ To use this library, you will need to define and register
callback functions that will be invoked to write data to the
resulting archive.
These functions are registered by calling
-.Fn archive_write_open :
+.Fn archive_write_open2 :
.Bl -item -offset indent
.It
.Ft typedef int
@@ -162,6 +177,8 @@ If the open fails, it should call
.Fn archive_set_error
to register an error code and message and return
.Cm ARCHIVE_FATAL .
+Please note that if open fails, close is not called and resources must be
+freed inside the open callback or with the free callback.
.Bl -item -offset indent
.It
.Ft typedef la_ssize_t
@@ -192,7 +209,8 @@ to register an error code and message and return -1.
.El
.Pp
The close callback is invoked by archive_close when
-the archive processing is complete.
+the archive processing is complete. If the open callback fails, the close
+callback is not invoked.
The callback should return
.Cm ARCHIVE_OK
on success.
@@ -200,7 +218,14 @@ On failure, the callback should invoke
.Fn archive_set_error
to register an error code and message and
return
-.Cm ARCHIVE_FATAL .
+.Bl -item -offset indent
+.It
+.Ft typedef int
+.Fn archive_free_callback "struct archive *" "void *client_data"
+.El
+.Pp
+The free callback is always invoked on archive_free.
+The return code of this callback is not processed.
.Pp
Note that if the client-provided write callback function
returns a non-zero value, that error will be propagated back to the caller
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_fd.c b/Utilities/cmlibarchive/libarchive/archive_write_open_fd.c
index d5c426cf9..b8d491faa 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_fd.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_fd.c
@@ -54,7 +54,7 @@ struct write_fd_data {
int fd;
};
-static int file_close(struct archive *, void *);
+static int file_free(struct archive *, void *);
static int file_open(struct archive *, void *);
static ssize_t file_write(struct archive *, void *, const void *buff, size_t);
@@ -72,8 +72,8 @@ archive_write_open_fd(struct archive *a, int fd)
#if defined(__CYGWIN__) || defined(_WIN32)
setmode(mine->fd, O_BINARY);
#endif
- return (archive_write_open(a, mine,
- file_open, file_write, file_close));
+ return (archive_write_open2(a, mine,
+ file_open, file_write, NULL, file_free));
}
static int
@@ -134,11 +134,13 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
}
static int
-file_close(struct archive *a, void *client_data)
+file_free(struct archive *a, void *client_data)
{
struct write_fd_data *mine = (struct write_fd_data *)client_data;
(void)a; /* UNUSED */
+ if (mine == NULL)
+ return (ARCHIVE_OK);
free(mine);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_file.c b/Utilities/cmlibarchive/libarchive/archive_write_open_file.c
index f6b141239..bf5b55a67 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_file.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_file.c
@@ -51,7 +51,7 @@ struct write_FILE_data {
FILE *f;
};
-static int file_close(struct archive *, void *);
+static int file_free(struct archive *, void *);
static int file_open(struct archive *, void *);
static ssize_t file_write(struct archive *, void *, const void *buff, size_t);
@@ -66,8 +66,8 @@ archive_write_open_FILE(struct archive *a, FILE *f)
return (ARCHIVE_FATAL);
}
mine->f = f;
- return (archive_write_open(a, mine,
- file_open, file_write, file_close));
+ return (archive_write_open2(a, mine, file_open, file_write,
+ NULL, file_free));
}
static int
@@ -99,11 +99,13 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
}
static int
-file_close(struct archive *a, void *client_data)
+file_free(struct archive *a, void *client_data)
{
struct write_FILE_data *mine = client_data;
(void)a; /* UNUSED */
+ if (mine == NULL)
+ return (ARCHIVE_OK);
free(mine);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
index 66e0dfee9..9ceefb19b 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_filename.c
@@ -62,6 +62,7 @@ struct write_file_data {
};
static int file_close(struct archive *, void *);
+static int file_free(struct archive *, void *);
static int file_open(struct archive *, void *);
static ssize_t file_write(struct archive *, void *, const void *buff, size_t);
static int open_filename(struct archive *, int, const void *);
@@ -123,8 +124,8 @@ open_filename(struct archive *a, int mbs_fn, const void *filename)
return (ARCHIVE_FAILED);
}
mine->fd = -1;
- return (archive_write_open(a, mine,
- file_open, file_write, file_close));
+ return (archive_write_open2(a, mine,
+ file_open, file_write, file_close, file_free));
}
static int
@@ -244,9 +245,25 @@ file_close(struct archive *a, void *client_data)
(void)a; /* UNUSED */
+ if (mine == NULL)
+ return (ARCHIVE_FATAL);
+
if (mine->fd >= 0)
close(mine->fd);
+ return (ARCHIVE_OK);
+}
+
+static int
+file_free(struct archive *a, void *client_data)
+{
+ struct write_file_data *mine = (struct write_file_data *)client_data;
+
+ (void)a; /* UNUSED */
+
+ if (mine == NULL)
+ return (ARCHIVE_OK);
+
archive_mstring_clean(&mine->filename);
free(mine);
return (ARCHIVE_OK);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
index ea6ae0ac5..a8a0b817f 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_open_memory.c
@@ -39,7 +39,7 @@ struct write_memory_data {
unsigned char * buff;
};
-static int memory_write_close(struct archive *, void *);
+static int memory_write_free(struct archive *, void *);
static int memory_write_open(struct archive *, void *);
static ssize_t memory_write(struct archive *, void *, const void *buff, size_t);
@@ -61,8 +61,8 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t
mine->buff = buff;
mine->size = buffSize;
mine->client_size = used;
- return (archive_write_open(a, mine,
- memory_write_open, memory_write, memory_write_close));
+ return (archive_write_open2(a, mine,
+ memory_write_open, memory_write, NULL, memory_write_free));
}
static int
@@ -103,11 +103,13 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng
}
static int
-memory_write_close(struct archive *a, void *client_data)
+memory_write_free(struct archive *a, void *client_data)
{
struct write_memory_data *mine;
(void)a; /* UNUSED */
mine = client_data;
+ if (mine == NULL)
+ return (ARCHIVE_OK);
free(mine);
return (ARCHIVE_OK);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_private.h b/Utilities/cmlibarchive/libarchive/archive_write_private.h
index 27cba0392..155fdd734 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_private.h
+++ b/Utilities/cmlibarchive/libarchive/archive_write_private.h
@@ -89,6 +89,7 @@ struct archive_write {
archive_open_callback *client_opener;
archive_write_callback *client_writer;
archive_close_callback *client_closer;
+ archive_free_callback *client_freer;
void *client_data;
/*
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format.c
index 12de08077..7dbe7b9a2 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format.c
@@ -82,7 +82,7 @@ void
__archive_write_entry_filetype_unsupported(struct archive *a,
struct archive_entry *entry, const char *format)
{
- char *name = NULL;
+ const char *name = NULL;
switch (archive_entry_filetype(entry)) {
/*
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
index 69af814f7..7f2e6ac90 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c
@@ -1927,8 +1927,8 @@ compression_init_encoder_lzma(struct archive *a,
return (ARCHIVE_FATAL);
}
lzmafilters = (lzma_filter *)(strm+1);
- if (level > 6)
- level = 6;
+ if (level > 9)
+ level = 9;
if (lzma_lzma_preset(&lzma_opt, level)) {
free(strm);
lastrm->real_stream = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
index 729f9c775..e06673352 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio.c
@@ -250,7 +250,7 @@ archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
const char *path;
size_t len;
- if (archive_entry_filetype(entry) == 0) {
+ if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
archive_set_error(&a->archive, -1, "Filetype required");
return (ARCHIVE_FAILED);
}
@@ -348,7 +348,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
if (archive_entry_filetype(entry) == AE_IFBLK
|| archive_entry_filetype(entry) == AE_IFCHR)
- format_octal(archive_entry_dev(entry), h + c_rdev_offset, c_rdev_size);
+ format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
else
format_octal(0, h + c_rdev_offset, c_rdev_size);
format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
index 172fda62f..f0f39809d 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_cpio_newc.c
@@ -190,7 +190,7 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry)
const char *path;
size_t len;
- if (archive_entry_filetype(entry) == 0) {
+ if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
archive_set_error(&a->archive, -1, "Filetype required");
return (ARCHIVE_FAILED);
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
index 5db414f40..68e3fe3eb 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c
@@ -2178,7 +2178,8 @@ get_system_identitier(char *system_id, size_t size)
strncpy(system_id, "Windows", size-1);
system_id[size-1] = '\0';
#else
-#error no way to get the system identifier on your platform.
+ strncpy(system_id, "Unknown", size-1);
+ system_id[size-1] = '\0';
#endif
}
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
index aa41e9acc..619b7714e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_mtree.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171
#include "archive.h"
#include "archive_digest_private.h"
#include "archive_entry.h"
+#include "archive_entry_private.h"
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_string.h"
@@ -82,24 +83,7 @@ struct dir_info {
struct reg_info {
int compute_sum;
uint32_t crc;
-#ifdef ARCHIVE_HAS_MD5
- unsigned char buf_md5[16];
-#endif
-#ifdef ARCHIVE_HAS_RMD160
- unsigned char buf_rmd160[20];
-#endif
-#ifdef ARCHIVE_HAS_SHA1
- unsigned char buf_sha1[20];
-#endif
-#ifdef ARCHIVE_HAS_SHA256
- unsigned char buf_sha256[32];
-#endif
-#ifdef ARCHIVE_HAS_SHA384
- unsigned char buf_sha384[48];
-#endif
-#ifdef ARCHIVE_HAS_SHA512
- unsigned char buf_sha512[64];
-#endif
+ struct ae_digest digest;
};
struct mtree_entry {
@@ -1571,27 +1555,27 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg)
}
#ifdef ARCHIVE_HAS_MD5
if (mtree->compute_sum & F_MD5)
- archive_md5_final(&mtree->md5ctx, reg->buf_md5);
+ archive_md5_final(&mtree->md5ctx, reg->digest.md5);
#endif
#ifdef ARCHIVE_HAS_RMD160
if (mtree->compute_sum & F_RMD160)
- archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160);
+ archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
#endif
#ifdef ARCHIVE_HAS_SHA1
if (mtree->compute_sum & F_SHA1)
- archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1);
+ archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
#endif
#ifdef ARCHIVE_HAS_SHA256
if (mtree->compute_sum & F_SHA256)
- archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256);
+ archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
#endif
#ifdef ARCHIVE_HAS_SHA384
if (mtree->compute_sum & F_SHA384)
- archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384);
+ archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
#endif
#ifdef ARCHIVE_HAS_SHA512
if (mtree->compute_sum & F_SHA512)
- archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512);
+ archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
#endif
/* Save what types of sum are computed. */
reg->compute_sum = mtree->compute_sum;
@@ -1621,42 +1605,47 @@ sum_write(struct archive_string *str, struct reg_info *reg)
archive_string_sprintf(str, " cksum=%ju",
(uintmax_t)reg->crc);
}
+
+#define append_digest(_s, _r, _t) \
+ strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t))
+
#ifdef ARCHIVE_HAS_MD5
if (reg->compute_sum & F_MD5) {
archive_strcat(str, " md5digest=");
- strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5));
+ append_digest(str, reg, md5);
}
#endif
#ifdef ARCHIVE_HAS_RMD160
if (reg->compute_sum & F_RMD160) {
archive_strcat(str, " rmd160digest=");
- strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160));
+ append_digest(str, reg, rmd160);
}
#endif
#ifdef ARCHIVE_HAS_SHA1
if (reg->compute_sum & F_SHA1) {
archive_strcat(str, " sha1digest=");
- strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1));
+ append_digest(str, reg, sha1);
}
#endif
#ifdef ARCHIVE_HAS_SHA256
if (reg->compute_sum & F_SHA256) {
archive_strcat(str, " sha256digest=");
- strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256));
+ append_digest(str, reg, sha256);
}
#endif
#ifdef ARCHIVE_HAS_SHA384
if (reg->compute_sum & F_SHA384) {
archive_strcat(str, " sha384digest=");
- strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384));
+ append_digest(str, reg, sha384);
}
#endif
#ifdef ARCHIVE_HAS_SHA512
if (reg->compute_sum & F_SHA512) {
archive_strcat(str, " sha512digest=");
- strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512));
+ append_digest(str, reg, sha512);
}
#endif
+#undef append_digest
}
static int
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
index 3b0ffb38a..1e3537534 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c
@@ -681,7 +681,8 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s)
{
struct xar *xar;
enum la_zaction run;
- size_t size, rsize;
+ size_t size = 0;
+ size_t rsize;
int r;
xar = (struct xar *)a->format_data;
@@ -2930,8 +2931,8 @@ compression_init_encoder_xz(struct archive *a,
return (ARCHIVE_FATAL);
}
lzmafilters = (lzma_filter *)(strm+1);
- if (level > 6)
- level = 6;
+ if (level > 9)
+ level = 9;
if (lzma_lzma_preset(&lzma_opt, level)) {
free(strm);
lastrm->real_stream = NULL;
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
index b0cd215b8..66a1f84ec 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c
@@ -584,6 +584,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED;
zip->entry_encryption = zip->encryption_type;
break;
+ case ENCRYPTION_NONE:
default:
break;
}
@@ -710,6 +711,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
+ AUTH_CODE_SIZE;
version_needed = 20;
break;
+ case ENCRYPTION_NONE:
default:
break;
}
@@ -762,6 +764,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
if (version_needed < 20)
version_needed = 20;
break;
+ case ENCRYPTION_NONE:
default:
break;
}
@@ -1029,6 +1032,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
zip->cctx_valid = zip->hctx_valid = 1;
}
break;
+ case ENCRYPTION_NONE:
default:
break;
}
@@ -1117,6 +1121,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
break;
#endif
+ case COMPRESSION_UNSPECIFIED:
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Invalid ZIP compression type");
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3 b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
index cffe571e9..d4a52e322 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
+++ b/Utilities/cmlibarchive/libarchive/archive_write_set_options.3
@@ -255,7 +255,8 @@ If supported, the default value is read from
.Bl -tag -compact -width indent
.It Cm compression-level
The value is interpreted as a decimal integer specifying the
-compression level. Supported values are from 1 to 22.
+compression level. Supported values depend on the library version,
+common values are from 1 to 22.
.El
.It Format 7zip
.Bl -tag -compact -width indent
diff --git a/Utilities/cmlibarchive/libarchive/config_freebsd.h b/Utilities/cmlibarchive/libarchive/config_freebsd.h
index f16fd3495..a484618b4 100644
--- a/Utilities/cmlibarchive/libarchive/config_freebsd.h
+++ b/Utilities/cmlibarchive/libarchive/config_freebsd.h
@@ -24,6 +24,7 @@
*
* $FreeBSD$
*/
+#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
#include <osreldate.h>
@@ -183,6 +184,7 @@
#define HAVE_STRFTIME 1
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
+#define HAVE_STRNLEN 1
#define HAVE_STRRCHR 1
#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
diff --git a/Utilities/cmlibarchive/libarchive/cpio.5 b/Utilities/cmlibarchive/libarchive/cpio.5
index 1a2886f08..a91f0c596 100644
--- a/Utilities/cmlibarchive/libarchive/cpio.5
+++ b/Utilities/cmlibarchive/libarchive/cpio.5
@@ -244,7 +244,7 @@ Note that this format supports only 4 gigabyte files (unlike the
older ASCII format, which supports 8 gigabyte files).
.Pp
In this format, hardlinked files are handled by setting the
-filesize to zero for each entry except the last one that
+filesize to zero for each entry except the first one that
appears in the archive.
.Ss New CRC Format
The CRC format is identical to the new ASCII format described
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork.h b/Utilities/cmlibarchive/libarchive/filter_fork.h
index 908e7cdd4..2bf290c4d 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork.h
+++ b/Utilities/cmlibarchive/libarchive/filter_fork.h
@@ -32,8 +32,13 @@
#error This header is only to be used internally to libarchive.
#endif
-pid_t
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout);
+int
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE *out_child);
+#else
+ pid_t *out_child);
+#endif
void
__archive_check_child(int in, int out);
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_posix.c b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c
index 02dbd4bb4..ac255c4f8 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork_posix.c
+++ b/Utilities/cmlibarchive/libarchive/filter_fork_posix.c
@@ -72,8 +72,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00
#include "filter_fork.h"
-pid_t
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
+int
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
+ pid_t *out_child)
{
pid_t child;
int stdin_pipe[2], stdout_pipe[2], tmp;
@@ -177,7 +178,8 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
__archive_cmdline_free(cmdline);
- return child;
+ *out_child = child;
+ return ARCHIVE_OK;
#if HAVE_POSIX_SPAWNP
actions_inited:
@@ -192,7 +194,7 @@ stdin_opened:
close(stdin_pipe[1]);
state_allocated:
__archive_cmdline_free(cmdline);
- return -1;
+ return ARCHIVE_FAILED;
}
void
diff --git a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
index ad271fe68..8d11179f3 100644
--- a/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
+++ b/Utilities/cmlibarchive/libarchive/filter_fork_windows.c
@@ -31,8 +31,9 @@
#include "filter_fork.h"
-pid_t
-__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
+int
+__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout,
+ HANDLE *out_child)
{
HANDLE childStdout[2], childStdin[2],childStderr;
SECURITY_ATTRIBUTES secAtts;
@@ -44,6 +45,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
char *arg0, *ext;
int i, l;
DWORD fl, fl_old;
+ HANDLE child;
childStdout[0] = childStdout[1] = INVALID_HANDLE_VALUE;
childStdin[0] = childStdin[1] = INVALID_HANDLE_VALUE;
@@ -154,13 +156,20 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
*child_stdout = _open_osfhandle((intptr_t)childStdout[0], _O_RDONLY);
*child_stdin = _open_osfhandle((intptr_t)childStdin[1], _O_WRONLY);
+ child = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
+ childInfo.dwProcessId);
+ if (child == NULL) // INVALID_HANDLE_VALUE ?
+ goto fail;
+
+ *out_child = child;
+
CloseHandle(childStdout[1]);
CloseHandle(childStdin[0]);
archive_string_free(&cmdline);
archive_string_free(&fullpath);
__archive_cmdline_free(acmd);
- return (childInfo.dwProcessId);
+ return ARCHIVE_OK;
fail:
if (childStdout[0] != INVALID_HANDLE_VALUE)
@@ -176,7 +185,7 @@ fail:
archive_string_free(&cmdline);
archive_string_free(&fullpath);
__archive_cmdline_free(acmd);
- return (-1);
+ return ARCHIVE_FAILED;
}
void
diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h
index f86357b4e..9b5d5dc63 100644
--- a/Utilities/cmlibuv/include/uv/win.h
+++ b/Utilities/cmlibuv/include/uv/win.h
@@ -45,7 +45,14 @@ typedef struct pollfd {
#endif
#include <mswsock.h>
+// Disable the typedef in mstcpip.h of MinGW.
+#define _TCP_INITIAL_RTO_PARAMETERS _TCP_INITIAL_RTO_PARAMETERS__AVOID
+#define TCP_INITIAL_RTO_PARAMETERS TCP_INITIAL_RTO_PARAMETERS__AVOID
+#define PTCP_INITIAL_RTO_PARAMETERS PTCP_INITIAL_RTO_PARAMETERS__AVOID
#include <ws2tcpip.h>
+#undef _TCP_INITIAL_RTO_PARAMETERS
+#undef TCP_INITIAL_RTO_PARAMETERS
+#undef PTCP_INITIAL_RTO_PARAMETERS
#include <windows.h>
#include <process.h>
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index e6d61ee2d..4245e027a 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -72,8 +72,6 @@ extern char** environ;
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
-# include <sys/param.h>
-# include <sys/cpuset.h>
# if defined(__FreeBSD__)
# define uv__accept4 accept4
# endif
@@ -82,6 +80,11 @@ extern char** environ;
# endif
#endif
+#if defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+#endif
+
#if defined(__MVS__)
#include <sys/ioctl.h>
#endif
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 04718dbdb..aada889e1 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -169,7 +169,10 @@ static WCHAR* search_path_join_test(const WCHAR* dir,
size_t cwd_len) {
WCHAR *result, *result_pos;
DWORD attrs;
- if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') {
+ if (
+ (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') ||
+ (dir_len > 2 && dir[0] == L'/' && dir[1] == L'/')
+ ) {
/* It's a UNC path so ignore cwd */
cwd_len = 0;
} else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {
diff --git a/Utilities/cmzstd/README.md b/Utilities/cmzstd/README.md
index 5c300fdc4..dcca7662d 100644
--- a/Utilities/cmzstd/README.md
+++ b/Utilities/cmzstd/README.md
@@ -176,6 +176,12 @@ Going into `build` directory, you will find additional possibilities:
You can build the zstd binary via buck by executing: `buck build programs:zstd` from the root of the repo.
The output binary will be in `buck-out/gen/programs/`.
+## Testing
+
+You can run quick local smoke tests by executing the `playTest.sh` script from the `src/tests` directory.
+Two env variables `$ZSTD_BIN` and `$DATAGEN_BIN` are needed for the test script to locate the zstd and datagen binary.
+For information on CI testing, please refer to TESTING.md
+
## Status
Zstandard is currently deployed within Facebook. It is used continuously to compress large amounts of data in multiple formats and use cases.
@@ -187,7 +193,7 @@ Zstandard is dual-licensed under [BSD](LICENSE) and [GPLv2](COPYING).
## Contributing
-The "dev" branch is the one where all contributions are merged before reaching "master".
-If you plan to propose a patch, please commit into the "dev" branch, or its own feature branch.
-Direct commit to "master" are not permitted.
+The `dev` branch is the one where all contributions are merged before reaching `release`.
+If you plan to propose a patch, please commit into the `dev` branch, or its own feature branch.
+Direct commit to `release` are not permitted.
For more information, please read [CONTRIBUTING](CONTRIBUTING.md).
diff --git a/Utilities/cmzstd/lib/common/bitstream.h b/Utilities/cmzstd/lib/common/bitstream.h
index 37b99c01e..2e5a933ad 100644
--- a/Utilities/cmzstd/lib/common/bitstream.h
+++ b/Utilities/cmzstd/lib/common/bitstream.h
@@ -1,7 +1,7 @@
/* ******************************************************************
* bitstream
* Part of FSE library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -17,7 +17,6 @@
#if defined (__cplusplus)
extern "C" {
#endif
-
/*
* This API consists of small unitary functions, which must be inlined for best performance.
* Since link-time-optimization is not available for all compilers,
@@ -36,10 +35,12 @@ extern "C" {
/*=========================================
* Target specific
=========================================*/
-#if defined(__BMI__) && defined(__GNUC__)
-# include <immintrin.h> /* support for bextr (experimental) */
-#elif defined(__ICCARM__)
-# include <intrinsics.h>
+#ifndef ZSTD_NO_INTRINSICS
+# if defined(__BMI__) && defined(__GNUC__)
+# include <immintrin.h> /* support for bextr (experimental) */
+# elif defined(__ICCARM__)
+# include <intrinsics.h>
+# endif
#endif
#define STREAM_ACCUMULATOR_MIN_32 25
@@ -141,8 +142,12 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val)
assert(val != 0);
{
# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- return _BitScanReverse ( &r, val ) ? (unsigned)r : 0;
+# if STATIC_BMI2 == 1
+ return _lzcnt_u32(val) ^ 31;
+# else
+ unsigned long r = 0;
+ return _BitScanReverse(&r, val) ? (unsigned)r : 0;
+# endif
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
return __builtin_clz (val) ^ 31;
# elif defined(__ICCARM__) /* IAR Intrinsic */
@@ -198,7 +203,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
size_t value, unsigned nbBits)
{
- MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32);
+ DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);
assert(nbBits < BIT_MASK_SIZE);
assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
@@ -271,7 +276,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
*/
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
{
- if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
+ if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
bitD->start = (const char*)srcBuffer;
bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
@@ -317,12 +322,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
return srcSize;
}
-MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
{
return bitContainer >> start;
}
-MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
{
U32 const regMask = sizeof(bitContainer)*8 - 1;
/* if start > regMask, bitstream is corrupted, and result is undefined */
@@ -330,10 +335,14 @@ MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 co
return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
}
-MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
{
+#if defined(STATIC_BMI2) && STATIC_BMI2 == 1
+ return _bzhi_u64(bitContainer, nbBits);
+#else
assert(nbBits < BIT_MASK_SIZE);
return bitContainer & BIT_mask[nbBits];
+#endif
}
/*! BIT_lookBits() :
@@ -342,7 +351,7 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
* On 32-bits, maxNbBits==24.
* On 64-bits, maxNbBits==56.
* @return : value extracted */
-MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
{
/* arbitrate between double-shift and shift+mask */
#if 1
@@ -365,7 +374,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
}
-MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
+MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
{
bitD->bitsConsumed += nbBits;
}
@@ -374,7 +383,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
* Read (consume) next n bits from local register and update.
* Pay attention to not read more than nbBits contained into local register.
* @return : extracted value. */
-MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
{
size_t const value = BIT_lookBits(bitD, nbBits);
BIT_skipBits(bitD, nbBits);
diff --git a/Utilities/cmzstd/lib/common/compiler.h b/Utilities/cmzstd/lib/common/compiler.h
index 95e948352..f71785563 100644
--- a/Utilities/cmzstd/lib/common/compiler.h
+++ b/Utilities/cmzstd/lib/common/compiler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -39,6 +39,17 @@
#endif
/**
+ On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
+ This explictly marks such functions as __cdecl so that the code will still compile
+ if a CC other than __cdecl has been made the default.
+*/
+#if defined(_MSC_VER)
+# define WIN_CDECL __cdecl
+#else
+# define WIN_CDECL
+#endif
+
+/**
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
* parameters. They must be inlined for the compiler to eliminate the constant
* branches.
@@ -79,6 +90,7 @@
# endif
#endif
+
/* target attribute */
#ifndef __has_attribute
#define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
@@ -114,12 +126,12 @@
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
# define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
# define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
-# elif defined(__aarch64__)
-# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
-# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
+# elif defined(__aarch64__)
+# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
+# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
# else
# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
@@ -139,7 +151,7 @@
/* vectorization
* older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */
-#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__)
+#if !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__LCC__) && defined(__GNUC__)
# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
# else
@@ -172,4 +184,106 @@
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
#endif
+/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/
+#ifndef STATIC_BMI2
+# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86))
+# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2
+# define STATIC_BMI2 1
+# endif
+# endif
+#endif
+
+#ifndef STATIC_BMI2
+ #define STATIC_BMI2 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+/* detects whether we are being compiled under msan */
+#ifndef ZSTD_MEMORY_SANITIZER
+# if __has_feature(memory_sanitizer)
+# define ZSTD_MEMORY_SANITIZER 1
+# else
+# define ZSTD_MEMORY_SANITIZER 0
+# endif
+#endif
+
+#if ZSTD_MEMORY_SANITIZER
+/* Not all platforms that support msan provide sanitizers/msan_interface.h.
+ * We therefore declare the functions we need ourselves, rather than trying to
+ * include the header file... */
+#include <stddef.h> /* size_t */
+#define ZSTD_DEPS_NEED_STDINT
+#include "zstd_deps.h" /* intptr_t */
+
+/* Make memory region fully initialized (without changing its contents). */
+void __msan_unpoison(const volatile void *a, size_t size);
+
+/* Make memory region fully uninitialized (without changing its contents).
+ This is a legacy interface that does not update origin information. Use
+ __msan_allocated_memory() instead. */
+void __msan_poison(const volatile void *a, size_t size);
+
+/* Returns the offset of the first (at least partially) poisoned byte in the
+ memory range, or -1 if the whole range is good. */
+intptr_t __msan_test_shadow(const volatile void *x, size_t size);
+#endif
+
+/* detects whether we are being compiled under asan */
+#ifndef ZSTD_ADDRESS_SANITIZER
+# if __has_feature(address_sanitizer)
+# define ZSTD_ADDRESS_SANITIZER 1
+# elif defined(__SANITIZE_ADDRESS__)
+# define ZSTD_ADDRESS_SANITIZER 1
+# else
+# define ZSTD_ADDRESS_SANITIZER 0
+# endif
+#endif
+
+#if ZSTD_ADDRESS_SANITIZER
+/* Not all platforms that support asan provide sanitizers/asan_interface.h.
+ * We therefore declare the functions we need ourselves, rather than trying to
+ * include the header file... */
+#include <stddef.h> /* size_t */
+
+/**
+ * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.
+ *
+ * This memory must be previously allocated by your program. Instrumented
+ * code is forbidden from accessing addresses in this region until it is
+ * unpoisoned. This function is not guaranteed to poison the entire region -
+ * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan
+ * alignment restrictions.
+ *
+ * \note This function is not thread-safe because no two threads can poison or
+ * unpoison memory in the same memory region simultaneously.
+ *
+ * \param addr Start of memory region.
+ * \param size Size of memory region. */
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+
+/**
+ * Marks a memory region (<c>[addr, addr+size)</c>) as addressable.
+ *
+ * This memory must be previously allocated by your program. Accessing
+ * addresses in this region is allowed until this region is poisoned again.
+ * This function could unpoison a super-region of <c>[addr, addr+size)</c> due
+ * to ASan alignment restrictions.
+ *
+ * \note This function is not thread-safe because no two threads can
+ * poison or unpoison memory in the same memory region simultaneously.
+ *
+ * \param addr Start of memory region.
+ * \param size Size of memory region. */
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#endif
+
#endif /* ZSTD_COMPILER_H */
diff --git a/Utilities/cmzstd/lib/common/cpu.h b/Utilities/cmzstd/lib/common/cpu.h
index 6e8a974f6..8acd33be3 100644
--- a/Utilities/cmzstd/lib/common/cpu.h
+++ b/Utilities/cmzstd/lib/common/cpu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Facebook, Inc.
+ * Copyright (c) Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -16,8 +16,6 @@
* https://github.com/facebook/folly/blob/master/folly/CpuId.h
*/
-#include <string.h>
-
#include "mem.h"
#ifdef _MSC_VER
diff --git a/Utilities/cmzstd/lib/common/debug.c b/Utilities/cmzstd/lib/common/debug.c
index f303f4a2e..bb863c9ea 100644
--- a/Utilities/cmzstd/lib/common/debug.c
+++ b/Utilities/cmzstd/lib/common/debug.c
@@ -1,7 +1,7 @@
/* ******************************************************************
* debug
* Part of FSE library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
diff --git a/Utilities/cmzstd/lib/common/debug.h b/Utilities/cmzstd/lib/common/debug.h
index ac6224888..3b2a320a1 100644
--- a/Utilities/cmzstd/lib/common/debug.h
+++ b/Utilities/cmzstd/lib/common/debug.h
@@ -1,7 +1,7 @@
/* ******************************************************************
* debug
* Part of FSE library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -51,15 +51,6 @@ extern "C" {
#endif
-/* DEBUGFILE can be defined externally,
- * typically through compiler command line.
- * note : currently useless.
- * Value must be stderr or stdout */
-#ifndef DEBUGFILE
-# define DEBUGFILE stderr
-#endif
-
-
/* recommended values for DEBUGLEVEL :
* 0 : release mode, no debug, all run-time checks disabled
* 1 : enables assert() only, no display
@@ -76,7 +67,8 @@ extern "C" {
*/
#if (DEBUGLEVEL>=1)
-# include <assert.h>
+# define ZSTD_DEPS_NEED_ASSERT
+# include "zstd_deps.h"
#else
# ifndef assert /* assert may be already defined, due to prior #include <assert.h> */
# define assert(condition) ((void)0) /* disable assert (default) */
@@ -84,7 +76,8 @@ extern "C" {
#endif
#if (DEBUGLEVEL>=2)
-# include <stdio.h>
+# define ZSTD_DEPS_NEED_IO
+# include "zstd_deps.h"
extern int g_debuglevel; /* the variable is only declared,
it actually lives in debug.c,
and is shared by the whole process.
@@ -92,14 +85,14 @@ extern int g_debuglevel; /* the variable is only declared,
It's useful when enabling very verbose levels
on selective conditions (such as position in src) */
-# define RAWLOG(l, ...) { \
- if (l<=g_debuglevel) { \
- fprintf(stderr, __VA_ARGS__); \
+# define RAWLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ ZSTD_DEBUG_PRINT(__VA_ARGS__); \
} }
-# define DEBUGLOG(l, ...) { \
- if (l<=g_debuglevel) { \
- fprintf(stderr, __FILE__ ": " __VA_ARGS__); \
- fprintf(stderr, " \n"); \
+# define DEBUGLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
+ ZSTD_DEBUG_PRINT(" \n"); \
} }
#else
# define RAWLOG(l, ...) {} /* disabled */
diff --git a/Utilities/cmzstd/lib/common/entropy_common.c b/Utilities/cmzstd/lib/common/entropy_common.c
index 9d3e4e8e3..41cd69566 100644
--- a/Utilities/cmzstd/lib/common/entropy_common.c
+++ b/Utilities/cmzstd/lib/common/entropy_common.c
@@ -1,6 +1,6 @@
/* ******************************************************************
* Common functions of New Generation Entropy library
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -38,8 +38,31 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
/*-**************************************************************
* FSE NCount encoding-decoding
****************************************************************/
-size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
- const void* headerBuffer, size_t hbSize)
+static U32 FSE_ctz(U32 val)
+{
+ assert(val != 0);
+ {
+# if defined(_MSC_VER) /* Visual */
+ unsigned long r=0;
+ return _BitScanForward(&r, val) ? (unsigned)r : 0;
+# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
+ return __builtin_ctz(val);
+# elif defined(__ICCARM__) /* IAR Intrinsic */
+ return __CTZ(val);
+# else /* Software version */
+ U32 count = 0;
+ while ((val & 1) == 0) {
+ val >>= 1;
+ ++count;
+ }
+ return count;
+# endif
+ }
+}
+
+FORCE_INLINE_TEMPLATE
+size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
{
const BYTE* const istart = (const BYTE*) headerBuffer;
const BYTE* const iend = istart + hbSize;
@@ -50,23 +73,23 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
U32 bitStream;
int bitCount;
unsigned charnum = 0;
+ unsigned const maxSV1 = *maxSVPtr + 1;
int previous0 = 0;
- if (hbSize < 4) {
- /* This function only works when hbSize >= 4 */
- char buffer[4];
- memset(buffer, 0, sizeof(buffer));
- memcpy(buffer, headerBuffer, hbSize);
+ if (hbSize < 8) {
+ /* This function only works when hbSize >= 8 */
+ char buffer[8] = {0};
+ ZSTD_memcpy(buffer, headerBuffer, hbSize);
{ size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
buffer, sizeof(buffer));
if (FSE_isError(countSize)) return countSize;
if (countSize > hbSize) return ERROR(corruption_detected);
return countSize;
} }
- assert(hbSize >= 4);
+ assert(hbSize >= 8);
/* init */
- memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */
+ ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */
bitStream = MEM_readLE32(ip);
nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
@@ -77,36 +100,58 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
threshold = 1<<nbBits;
nbBits++;
- while ((remaining>1) & (charnum<=*maxSVPtr)) {
+ for (;;) {
if (previous0) {
- unsigned n0 = charnum;
- while ((bitStream & 0xFFFF) == 0xFFFF) {
- n0 += 24;
- if (ip < iend-5) {
- ip += 2;
- bitStream = MEM_readLE32(ip) >> bitCount;
+ /* Count the number of repeats. Each time the
+ * 2-bit repeat code is 0b11 there is another
+ * repeat.
+ * Avoid UB by setting the high bit to 1.
+ */
+ int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
+ while (repeats >= 12) {
+ charnum += 3 * 12;
+ if (LIKELY(ip <= iend-7)) {
+ ip += 3;
} else {
- bitStream >>= 16;
- bitCount += 16;
- } }
- while ((bitStream & 3) == 3) {
- n0 += 3;
- bitStream >>= 2;
- bitCount += 2;
+ bitCount -= (int)(8 * (iend - 7 - ip));
+ bitCount &= 31;
+ ip = iend - 4;
+ }
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
}
- n0 += bitStream & 3;
+ charnum += 3 * repeats;
+ bitStream >>= 2 * repeats;
+ bitCount += 2 * repeats;
+
+ /* Add the final repeat which isn't 0b11. */
+ assert((bitStream & 3) < 3);
+ charnum += bitStream & 3;
bitCount += 2;
- if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
- while (charnum < n0) normalizedCounter[charnum++] = 0;
- if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+
+ /* This is an error, but break and return an error
+ * at the end, because returning out of a loop makes
+ * it harder for the compiler to optimize.
+ */
+ if (charnum >= maxSV1) break;
+
+ /* We don't need to set the normalized count to 0
+ * because we already memset the whole buffer to 0.
+ */
+
+ if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
assert((bitCount >> 3) <= 3); /* For first condition to work */
ip += bitCount>>3;
bitCount &= 7;
- bitStream = MEM_readLE32(ip) >> bitCount;
} else {
- bitStream >>= 2;
- } }
- { int const max = (2*threshold-1) - remaining;
+ bitCount -= (int)(8 * (iend - 4 - ip));
+ bitCount &= 31;
+ ip = iend - 4;
+ }
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ }
+ {
+ int const max = (2*threshold-1) - remaining;
int count;
if ((bitStream & (threshold-1)) < (U32)max) {
@@ -119,24 +164,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
}
count--; /* extra accuracy */
- remaining -= count < 0 ? -count : count; /* -1 means +1 */
+ /* When it matters (small blocks), this is a
+ * predictable branch, because we don't use -1.
+ */
+ if (count >= 0) {
+ remaining -= count;
+ } else {
+ assert(count == -1);
+ remaining += count;
+ }
normalizedCounter[charnum++] = (short)count;
previous0 = !count;
- while (remaining < threshold) {
- nbBits--;
- threshold >>= 1;
+
+ assert(threshold > 1);
+ if (remaining < threshold) {
+ /* This branch can be folded into the
+ * threshold update condition because we
+ * know that threshold > 1.
+ */
+ if (remaining <= 1) break;
+ nbBits = BIT_highbit32(remaining) + 1;
+ threshold = 1 << (nbBits - 1);
}
+ if (charnum >= maxSV1) break;
- if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+ if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
ip += bitCount>>3;
bitCount &= 7;
} else {
bitCount -= (int)(8 * (iend - 4 - ip));
+ bitCount &= 31;
ip = iend - 4;
}
- bitStream = MEM_readLE32(ip) >> (bitCount & 31);
- } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ } }
if (remaining != 1) return ERROR(corruption_detected);
+ /* Only possible when there are too many zeros. */
+ if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);
if (bitCount > 32) return ERROR(corruption_detected);
*maxSVPtr = charnum-1;
@@ -144,6 +208,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
return ip-istart;
}
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t FSE_readNCount_body_default(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+
+#if DYNAMIC_BMI2
+TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+#endif
+
+size_t FSE_readNCount_bmi2(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+ }
+#endif
+ (void)bmi2;
+ return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+
+size_t FSE_readNCount(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);
+}
+
/*! HUF_readStats() :
Read compact Huffman tree, saved by HUF_writeCTable().
@@ -156,6 +257,17 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize)
{
+ U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+ return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0);
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize,
+ int bmi2)
+{
U32 weightTotal;
const BYTE* ip = (const BYTE*) src;
size_t iSize;
@@ -163,7 +275,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
if (!srcSize) return ERROR(srcSize_wrong);
iSize = ip[0];
- /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */
+ /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */
if (iSize >= 128) { /* special header */
oSize = iSize - 127;
@@ -177,14 +289,14 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
huffWeight[n+1] = ip[n/2] & 15;
} } }
else { /* header compressed with FSE (normal case) */
- FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
- oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */
+ /* max (hwSize-1) values decoded, as last one is implied */
+ oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);
if (FSE_isError(oSize)) return oSize;
}
/* collect weight stats */
- memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
+ ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
weightTotal = 0;
{ U32 n; for (n=0; n<oSize; n++) {
if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected);
@@ -214,3 +326,37 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
*nbSymbolsPtr = (U32)(oSize+1);
return iSize+1;
}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);
+}
+
+#if DYNAMIC_BMI2
+static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);
+}
+#endif
+
+size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize,
+ int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
+ }
+#endif
+ (void)bmi2;
+ return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
+}
diff --git a/Utilities/cmzstd/lib/common/error_private.c b/Utilities/cmzstd/lib/common/error_private.c
index cd437529c..6d1135f8c 100644
--- a/Utilities/cmzstd/lib/common/error_private.c
+++ b/Utilities/cmzstd/lib/common/error_private.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -48,6 +48,7 @@ const char* ERR_getErrorString(ERR_enum code)
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
+ case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
case PREFIX(maxCode):
default: return notErrorCode;
}
diff --git a/Utilities/cmzstd/lib/common/error_private.h b/Utilities/cmzstd/lib/common/error_private.h
index 982cf8e9f..6d8b9f776 100644
--- a/Utilities/cmzstd/lib/common/error_private.h
+++ b/Utilities/cmzstd/lib/common/error_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -21,8 +21,8 @@ extern "C" {
/* ****************************************
* Dependencies
******************************************/
-#include <stddef.h> /* size_t */
-#include "zstd_errors.h" /* enum list */
+#include "../zstd_errors.h" /* enum list */
+#include "zstd_deps.h" /* size_t */
/* ****************************************
diff --git a/Utilities/cmzstd/lib/common/fse.h b/Utilities/cmzstd/lib/common/fse.h
index ff54e70ea..19dd4febc 100644
--- a/Utilities/cmzstd/lib/common/fse.h
+++ b/Utilities/cmzstd/lib/common/fse.h
@@ -1,7 +1,7 @@
/* ******************************************************************
* FSE : Finite State Entropy codec
* Public Prototypes declaration
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -23,7 +23,7 @@ extern "C" {
/*-*****************************************
* Dependencies
******************************************/
-#include <stddef.h> /* size_t, ptrdiff_t */
+#include "zstd_deps.h" /* size_t, ptrdiff_t */
/*-*****************************************
@@ -137,10 +137,16 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize
/*! FSE_normalizeCount():
normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
+ useLowProbCount is a boolean parameter which trades off compressed size for
+ faster header decoding. When it is set to 1, the compressed data will be slightly
+ smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be
+ faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0
+ is a good default, since header deserialization makes a big speed difference.
+ Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.
@return : tableLog,
or an errorCode, which can be tested using FSE_isError() */
FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
- const unsigned* count, size_t srcSize, unsigned maxSymbolValue);
+ const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
/*! FSE_NCountWriteBound():
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
@@ -228,6 +234,13 @@ FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
const void* rBuffer, size_t rBuffSize);
+/*! FSE_readNCount_bmi2():
+ * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.
+ */
+FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
+ unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
+ const void* rBuffer, size_t rBuffSize, int bmi2);
+
/*! Constructor and Destructor of FSE_DTable.
Note that its size depends on 'tableLog' */
typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
@@ -288,12 +301,12 @@ If there is an error, the function will return an error code, which can be teste
*******************************************/
/* FSE buffer bounds */
#define FSE_NCOUNTBOUND 512
-#define FSE_BLOCKBOUND(size) (size + (size>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
+#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
-#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
-#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
+#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
+#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog)))
/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
@@ -309,9 +322,9 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
/* FSE_compress_wksp() :
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
- * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
+ * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
*/
-#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
+#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
@@ -322,18 +335,30 @@ size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
/* FSE_buildCTable_wksp() :
* Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
- * `wkspSize` must be >= `(1<<tableLog)`.
+ * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
*/
+#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2)))
+#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
+#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
+#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
+FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
+/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
+
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
-size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog);
-/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
+#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
+#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
+size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
+/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
+
+size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
+/**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
typedef enum {
FSE_repeat_none, /**< Cannot use the previous table */
@@ -644,6 +669,9 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
#ifndef FSE_DEFAULT_MEMORY_USAGE
# define FSE_DEFAULT_MEMORY_USAGE 13
#endif
+#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
+# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
+#endif
/*!FSE_MAX_SYMBOL_VALUE :
* Maximum symbol value authorized.
@@ -677,7 +705,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
#endif
-#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)
+#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
#endif /* FSE_STATIC_LINKING_ONLY */
diff --git a/Utilities/cmzstd/lib/common/fse_decompress.c b/Utilities/cmzstd/lib/common/fse_decompress.c
index bcc2223cc..f4ff58fa0 100644
--- a/Utilities/cmzstd/lib/common/fse_decompress.c
+++ b/Utilities/cmzstd/lib/common/fse_decompress.c
@@ -1,6 +1,6 @@
/* ******************************************************************
* FSE : Finite State Entropy decoder
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -16,13 +16,14 @@
/* **************************************************************
* Includes
****************************************************************/
-#include <stdlib.h> /* malloc, free, qsort */
-#include <string.h> /* memcpy, memset */
+#include "debug.h" /* assert */
#include "bitstream.h"
#include "compiler.h"
#define FSE_STATIC_LINKING_ONLY
#include "fse.h"
#include "error_private.h"
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h"
/* **************************************************************
@@ -59,25 +60,27 @@
FSE_DTable* FSE_createDTable (unsigned tableLog)
{
if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
- return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
+ return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
}
void FSE_freeDTable (FSE_DTable* dt)
{
- free(dt);
+ ZSTD_free(dt);
}
-size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
+static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
{
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);
- U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];
+ U16* symbolNext = (U16*)workSpace;
+ BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);
U32 const maxSV1 = maxSymbolValue + 1;
U32 const tableSize = 1 << tableLog;
U32 highThreshold = tableSize-1;
/* Sanity Checks */
+ if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);
if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
@@ -95,11 +98,57 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
symbolNext[s] = normalizedCounter[s];
} } }
- memcpy(dt, &DTableH, sizeof(DTableH));
+ ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
}
/* Spread symbols */
- { U32 const tableMask = tableSize-1;
+ if (highThreshold == tableSize - 1) {
+ size_t const tableMask = tableSize-1;
+ size_t const step = FSE_TABLESTEP(tableSize);
+ /* First lay down the symbols in order.
+ * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
+ * misses since small blocks generally have small table logs, so nearly
+ * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
+ * our buffer to handle the over-write.
+ */
+ {
+ U64 const add = 0x0101010101010101ull;
+ size_t pos = 0;
+ U64 sv = 0;
+ U32 s;
+ for (s=0; s<maxSV1; ++s, sv += add) {
+ int i;
+ int const n = normalizedCounter[s];
+ MEM_write64(spread + pos, sv);
+ for (i = 8; i < n; i += 8) {
+ MEM_write64(spread + pos + i, sv);
+ }
+ pos += n;
+ }
+ }
+ /* Now we spread those positions across the table.
+ * The benefit of doing it in two stages is that we avoid the the
+ * variable size inner loop, which caused lots of branch misses.
+ * Now we can run through all the positions without any branch misses.
+ * We unroll the loop twice, since that is what emperically worked best.
+ */
+ {
+ size_t position = 0;
+ size_t s;
+ size_t const unroll = 2;
+ assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
+ for (s = 0; s < (size_t)tableSize; s += unroll) {
+ size_t u;
+ for (u = 0; u < unroll; ++u) {
+ size_t const uPosition = (position + (u * step)) & tableMask;
+ tableDecode[uPosition].symbol = spread[s + u];
+ }
+ position = (position + (unroll * step)) & tableMask;
+ }
+ assert(position == 0);
+ }
+ } else {
+ U32 const tableMask = tableSize-1;
U32 const step = FSE_TABLESTEP(tableSize);
U32 s, position = 0;
for (s=0; s<maxSV1; s++) {
@@ -124,6 +173,11 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned
return 0;
}
+size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);
+}
+
#ifndef FSE_COMMONDEFS_ONLY
@@ -251,36 +305,99 @@ size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
}
-size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog)
+size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+typedef struct {
+ short ncount[FSE_MAX_SYMBOL_VALUE + 1];
+ FSE_DTable dtable[1]; /* Dynamically sized */
+} FSE_DecompressWksp;
+
+
+FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
+ void* dst, size_t dstCapacity,
+ const void* cSrc, size_t cSrcSize,
+ unsigned maxLog, void* workSpace, size_t wkspSize,
+ int bmi2)
{
const BYTE* const istart = (const BYTE*)cSrc;
const BYTE* ip = istart;
- short counting[FSE_MAX_SYMBOL_VALUE+1];
unsigned tableLog;
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
+ FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
+
+ DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
+ if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
/* normal FSE decoding mode */
- size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
- if (FSE_isError(NCountLength)) return NCountLength;
- /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */
- if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
- ip += NCountLength;
- cSrcSize -= NCountLength;
+ {
+ size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
+ if (FSE_isError(NCountLength)) return NCountLength;
+ if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
+ assert(NCountLength <= cSrcSize);
+ ip += NCountLength;
+ cSrcSize -= NCountLength;
+ }
+
+ if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
+ workSpace = wksp->dtable + FSE_DTABLE_SIZE_U32(tableLog);
+ wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
+
+ CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
+
+ {
+ const void* ptr = wksp->dtable;
+ const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
+ const U32 fastMode = DTableH->fastMode;
- CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) );
+ /* select fast mode (static) */
+ if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
+ return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
+ }
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);
+}
+
+#if DYNAMIC_BMI2
+TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
+}
+#endif
- return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */
+size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
+ }
+#endif
+ (void)bmi2;
+ return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
}
typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
+size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) {
+ U32 wksp[FSE_BUILD_DTABLE_WKSP_SIZE_U32(FSE_TABLELOG_ABSOLUTE_MAX, FSE_MAX_SYMBOL_VALUE)];
+ return FSE_buildDTable_wksp(dt, normalizedCounter, maxSymbolValue, tableLog, wksp, sizeof(wksp));
+}
+
size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize)
{
- DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */
- return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG);
+ /* Static analyzer seems unable to understand this table will be properly initialized later */
+ U32 wksp[FSE_DECOMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
+ return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, FSE_MAX_TABLELOG, wksp, sizeof(wksp));
}
-
+#endif
#endif /* FSE_COMMONDEFS_ONLY */
diff --git a/Utilities/cmzstd/lib/common/huf.h b/Utilities/cmzstd/lib/common/huf.h
index ef432685d..3d47ced03 100644
--- a/Utilities/cmzstd/lib/common/huf.h
+++ b/Utilities/cmzstd/lib/common/huf.h
@@ -1,7 +1,7 @@
/* ******************************************************************
* huff0 huffman codec,
* part of Finite State Entropy library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -20,7 +20,7 @@ extern "C" {
#define HUF_H_298734234
/* *** Dependencies *** */
-#include <stddef.h> /* size_t */
+#include "zstd_deps.h" /* size_t */
/* *** library symbols visibility *** */
@@ -111,6 +111,8 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
/* *** Dependencies *** */
#include "mem.h" /* U32 */
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
/* *** Constants *** */
@@ -133,12 +135,16 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
/* static allocation of HUF's Compression Table */
+/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */
+struct HUF_CElt_s {
+ U16 val;
+ BYTE nbBits;
+}; /* typedef'd to HUF_CElt */
+typedef struct HUF_CElt_s HUF_CElt; /* consider it an incomplete type */
#define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */
#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))
#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
- U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \
- void* name##hv = &(name##hb); \
- HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */
+ HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */
/* static allocation of HUF's DTable */
typedef U32 HUF_DTable;
@@ -184,9 +190,9 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
* or to save and regenerate 'CTable' using external methods.
*/
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
-typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
+size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
@@ -226,6 +232,19 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize);
+/*! HUF_readStats_wksp() :
+ * Same as HUF_readStats() but takes an external workspace which must be
+ * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.
+ * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
+ */
+#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)
+#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))
+size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
+ U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workspace, size_t wkspSize,
+ int bmi2);
+
/** HUF_readCTable() :
* Loading a CTable saved with HUF_writeCTable() */
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);
@@ -260,7 +279,7 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
* a required workspace size greater than that specified in the following
* macro.
*/
-#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
+#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
#ifndef HUF_FORCE_DECOMPRESS_X2
@@ -332,6 +351,9 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS
#endif
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
#endif /* HUF_STATIC_LINKING_ONLY */
diff --git a/Utilities/cmzstd/lib/common/mem.h b/Utilities/cmzstd/lib/common/mem.h
index c3f98fcd0..9f3b81ab9 100644
--- a/Utilities/cmzstd/lib/common/mem.h
+++ b/Utilities/cmzstd/lib/common/mem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -18,8 +18,10 @@ extern "C" {
/*-****************************************
* Dependencies
******************************************/
-#include <stddef.h> /* size_t, ptrdiff_t */
-#include <string.h> /* memcpy */
+#include <stddef.h> /* size_t, ptrdiff_t */
+#include "compiler.h" /* __has_builtin */
+#include "debug.h" /* DEBUG_STATIC_ASSERT */
+#include "zstd_deps.h" /* ZSTD_memcpy */
/*-****************************************
@@ -39,93 +41,15 @@ extern "C" {
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
#endif
-#ifndef __has_builtin
-# define __has_builtin(x) 0 /* compat. with non-clang compilers */
-#endif
-
-/* code only tested on 32 and 64 bits systems */
-#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; }
-MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
-
-/* detects whether we are being compiled under msan */
-#if defined (__has_feature)
-# if __has_feature(memory_sanitizer)
-# define MEMORY_SANITIZER 1
-# endif
-#endif
-
-#if defined (MEMORY_SANITIZER)
-/* Not all platforms that support msan provide sanitizers/msan_interface.h.
- * We therefore declare the functions we need ourselves, rather than trying to
- * include the header file... */
-
-#include <stdint.h> /* intptr_t */
-
-/* Make memory region fully initialized (without changing its contents). */
-void __msan_unpoison(const volatile void *a, size_t size);
-
-/* Make memory region fully uninitialized (without changing its contents).
- This is a legacy interface that does not update origin information. Use
- __msan_allocated_memory() instead. */
-void __msan_poison(const volatile void *a, size_t size);
-
-/* Returns the offset of the first (at least partially) poisoned byte in the
- memory range, or -1 if the whole range is good. */
-intptr_t __msan_test_shadow(const volatile void *x, size_t size);
-#endif
-
-/* detects whether we are being compiled under asan */
-#if defined (__has_feature)
-# if __has_feature(address_sanitizer)
-# define ADDRESS_SANITIZER 1
-# endif
-#elif defined(__SANITIZE_ADDRESS__)
-# define ADDRESS_SANITIZER 1
-#endif
-
-#if defined (ADDRESS_SANITIZER)
-/* Not all platforms that support asan provide sanitizers/asan_interface.h.
- * We therefore declare the functions we need ourselves, rather than trying to
- * include the header file... */
-
-/**
- * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.
- *
- * This memory must be previously allocated by your program. Instrumented
- * code is forbidden from accessing addresses in this region until it is
- * unpoisoned. This function is not guaranteed to poison the entire region -
- * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan
- * alignment restrictions.
- *
- * \note This function is not thread-safe because no two threads can poison or
- * unpoison memory in the same memory region simultaneously.
- *
- * \param addr Start of memory region.
- * \param size Size of memory region. */
-void __asan_poison_memory_region(void const volatile *addr, size_t size);
-
-/**
- * Marks a memory region (<c>[addr, addr+size)</c>) as addressable.
- *
- * This memory must be previously allocated by your program. Accessing
- * addresses in this region is allowed until this region is poisoned again.
- * This function could unpoison a super-region of <c>[addr, addr+size)</c> due
- * to ASan alignment restrictions.
- *
- * \note This function is not thread-safe because no two threads can
- * poison or unpoison memory in the same memory region simultaneously.
- *
- * \param addr Start of memory region.
- * \param size Size of memory region. */
-void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
-#endif
-
-
/*-**************************************************************
* Basic Types
*****************************************************************/
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
-# include <stdint.h>
+# if defined(_AIX)
+# include <inttypes.h>
+# else
+# include <stdint.h> /* intptr_t */
+# endif
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef int16_t S16;
@@ -157,7 +81,53 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
/*-**************************************************************
-* Memory I/O
+* Memory I/O API
+*****************************************************************/
+/*=== Static platform detection ===*/
+MEM_STATIC unsigned MEM_32bits(void);
+MEM_STATIC unsigned MEM_64bits(void);
+MEM_STATIC unsigned MEM_isLittleEndian(void);
+
+/*=== Native unaligned read/write ===*/
+MEM_STATIC U16 MEM_read16(const void* memPtr);
+MEM_STATIC U32 MEM_read32(const void* memPtr);
+MEM_STATIC U64 MEM_read64(const void* memPtr);
+MEM_STATIC size_t MEM_readST(const void* memPtr);
+
+MEM_STATIC void MEM_write16(void* memPtr, U16 value);
+MEM_STATIC void MEM_write32(void* memPtr, U32 value);
+MEM_STATIC void MEM_write64(void* memPtr, U64 value);
+
+/*=== Little endian unaligned read/write ===*/
+MEM_STATIC U16 MEM_readLE16(const void* memPtr);
+MEM_STATIC U32 MEM_readLE24(const void* memPtr);
+MEM_STATIC U32 MEM_readLE32(const void* memPtr);
+MEM_STATIC U64 MEM_readLE64(const void* memPtr);
+MEM_STATIC size_t MEM_readLEST(const void* memPtr);
+
+MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
+MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
+MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
+MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
+MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
+
+/*=== Big endian unaligned read/write ===*/
+MEM_STATIC U32 MEM_readBE32(const void* memPtr);
+MEM_STATIC U64 MEM_readBE64(const void* memPtr);
+MEM_STATIC size_t MEM_readBEST(const void* memPtr);
+
+MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
+MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
+MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
+
+/*=== Byteswap ===*/
+MEM_STATIC U32 MEM_swap32(U32 in);
+MEM_STATIC U64 MEM_swap64(U64 in);
+MEM_STATIC size_t MEM_swapST(size_t in);
+
+
+/*-**************************************************************
+* Memory I/O Implementation
*****************************************************************/
/* MEM_FORCE_MEMORY_ACCESS :
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
@@ -234,37 +204,37 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v =
MEM_STATIC U16 MEM_read16(const void* memPtr)
{
- U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
+ U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
}
MEM_STATIC U32 MEM_read32(const void* memPtr)
{
- U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
+ U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
}
MEM_STATIC U64 MEM_read64(const void* memPtr)
{
- U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
+ U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
}
MEM_STATIC size_t MEM_readST(const void* memPtr)
{
- size_t val; memcpy(&val, memPtr, sizeof(val)); return val;
+ size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;
}
MEM_STATIC void MEM_write16(void* memPtr, U16 value)
{
- memcpy(memPtr, &value, sizeof(value));
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
}
MEM_STATIC void MEM_write32(void* memPtr, U32 value)
{
- memcpy(memPtr, &value, sizeof(value));
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
}
MEM_STATIC void MEM_write64(void* memPtr, U64 value)
{
- memcpy(memPtr, &value, sizeof(value));
+ ZSTD_memcpy(memPtr, &value, sizeof(value));
}
#endif /* MEM_FORCE_MEMORY_ACCESS */
@@ -336,7 +306,7 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
{
- return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
+ return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);
}
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
@@ -443,6 +413,9 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
MEM_writeBE64(memPtr, (U64)val);
}
+/* code only tested on 32 and 64 bits systems */
+MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
+
#if defined (__cplusplus)
}
diff --git a/Utilities/cmzstd/lib/common/pool.c b/Utilities/cmzstd/lib/common/pool.c
index aa4b4de0d..ea70b8b65 100644
--- a/Utilities/cmzstd/lib/common/pool.c
+++ b/Utilities/cmzstd/lib/common/pool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -10,9 +10,9 @@
/* ====== Dependencies ======= */
-#include <stddef.h> /* size_t */
+#include "zstd_deps.h" /* size_t */
#include "debug.h" /* assert */
-#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */
+#include "zstd_internal.h" /* ZSTD_customMalloc, ZSTD_customFree */
#include "pool.h"
/* ====== Compiler specifics ====== */
@@ -105,6 +105,10 @@ static void* POOL_thread(void* opaque) {
assert(0); /* Unreachable */
}
+POOL_ctx* ZSTD_createThreadPool(size_t numThreads) {
+ return POOL_create (numThreads, 0);
+}
+
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
}
@@ -115,14 +119,14 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
/* Check parameters */
if (!numThreads) { return NULL; }
/* Allocate the context and zero initialize */
- ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
+ ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem);
if (!ctx) { return NULL; }
/* Initialize the job queue.
* It needs one extra space since one space is wasted to differentiate
* empty and full queues.
*/
ctx->queueSize = queueSize + 1;
- ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem);
+ ctx->queue = (POOL_job*)ZSTD_customMalloc(ctx->queueSize * sizeof(POOL_job), customMem);
ctx->queueHead = 0;
ctx->queueTail = 0;
ctx->numThreadsBusy = 0;
@@ -136,7 +140,7 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
}
ctx->shutdown = 0;
/* Allocate space for the thread handles */
- ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
+ ctx->threads = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
ctx->threadCapacity = 0;
ctx->customMem = customMem;
/* Check for errors */
@@ -179,12 +183,14 @@ void POOL_free(POOL_ctx *ctx) {
ZSTD_pthread_mutex_destroy(&ctx->queueMutex);
ZSTD_pthread_cond_destroy(&ctx->queuePushCond);
ZSTD_pthread_cond_destroy(&ctx->queuePopCond);
- ZSTD_free(ctx->queue, ctx->customMem);
- ZSTD_free(ctx->threads, ctx->customMem);
- ZSTD_free(ctx, ctx->customMem);
+ ZSTD_customFree(ctx->queue, ctx->customMem);
+ ZSTD_customFree(ctx->threads, ctx->customMem);
+ ZSTD_customFree(ctx, ctx->customMem);
}
-
+void ZSTD_freeThreadPool (ZSTD_threadPool* pool) {
+ POOL_free (pool);
+}
size_t POOL_sizeof(POOL_ctx *ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
@@ -203,11 +209,11 @@ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
return 0;
}
/* numThreads > threadCapacity */
- { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
+ { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
if (!threadPool) return 1;
/* replace existing thread pool */
- memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
- ZSTD_free(ctx->threads, ctx->customMem);
+ ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
+ ZSTD_customFree(ctx->threads, ctx->customMem);
ctx->threads = threadPool;
/* Initialize additional threads */
{ size_t threadId;
@@ -301,7 +307,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
struct POOL_ctx_s {
int dummy;
};
-static POOL_ctx g_ctx;
+static POOL_ctx g_poolCtx;
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
@@ -311,11 +317,11 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM
(void)numThreads;
(void)queueSize;
(void)customMem;
- return &g_ctx;
+ return &g_poolCtx;
}
void POOL_free(POOL_ctx* ctx) {
- assert(!ctx || ctx == &g_ctx);
+ assert(!ctx || ctx == &g_poolCtx);
(void)ctx;
}
@@ -337,7 +343,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
size_t POOL_sizeof(POOL_ctx* ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
- assert(ctx == &g_ctx);
+ assert(ctx == &g_poolCtx);
return sizeof(*ctx);
}
diff --git a/Utilities/cmzstd/lib/common/pool.h b/Utilities/cmzstd/lib/common/pool.h
index 259bafc97..e18aa0708 100644
--- a/Utilities/cmzstd/lib/common/pool.h
+++ b/Utilities/cmzstd/lib/common/pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -16,7 +16,7 @@ extern "C" {
#endif
-#include <stddef.h> /* size_t */
+#include "zstd_deps.h"
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */
#include "../zstd.h"
diff --git a/Utilities/cmzstd/lib/common/threading.c b/Utilities/cmzstd/lib/common/threading.c
index e2edb313e..92cf57c19 100644
--- a/Utilities/cmzstd/lib/common/threading.c
+++ b/Utilities/cmzstd/lib/common/threading.c
@@ -78,11 +78,12 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr)
#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
-#include <stdlib.h>
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h"
int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
{
- *mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
+ *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
if (!*mutex)
return 1;
return pthread_mutex_init(*mutex, attr);
@@ -94,14 +95,14 @@ int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
return 0;
{
int const ret = pthread_mutex_destroy(*mutex);
- free(*mutex);
+ ZSTD_free(*mutex);
return ret;
}
}
int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
{
- *cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
+ *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
if (!*cond)
return 1;
return pthread_cond_init(*cond, attr);
@@ -113,7 +114,7 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
return 0;
{
int const ret = pthread_cond_destroy(*cond);
- free(*cond);
+ ZSTD_free(*cond);
return ret;
}
}
diff --git a/Utilities/cmzstd/lib/common/xxhash.c b/Utilities/cmzstd/lib/common/xxhash.c
index 3d7655eba..926b33604 100644
--- a/Utilities/cmzstd/lib/common/xxhash.c
+++ b/Utilities/cmzstd/lib/common/xxhash.c
@@ -1,6 +1,6 @@
/*
* xxHash - Fast Hash algorithm
- * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - xxHash homepage: http://www.xxhash.com
@@ -75,14 +75,12 @@
* Includes & Memory related functions
***************************************/
/* Modify the local functions below should you wish to use some other memory routines */
-/* for malloc(), free() */
-#include <stdlib.h>
-#include <stddef.h> /* size_t */
-static void* XXH_malloc(size_t s) { return malloc(s); }
-static void XXH_free (void* p) { free(p); }
-/* for memcpy() */
-#include <string.h>
-static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
+/* for ZSTD_malloc(), ZSTD_free() */
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */
+static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); }
+static void XXH_free (void* p) { ZSTD_free(p); }
+static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); }
#ifndef XXH_STATIC_LINKING_ONLY
# define XXH_STATIC_LINKING_ONLY
@@ -93,49 +91,13 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp
/* *************************************
* Compiler Specific Options
***************************************/
-#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
-# define INLINE_KEYWORD inline
-#else
-# define INLINE_KEYWORD
-#endif
-
-#if defined(__GNUC__) || defined(__ICCARM__)
-# define FORCE_INLINE_ATTR __attribute__((always_inline))
-#elif defined(_MSC_VER)
-# define FORCE_INLINE_ATTR __forceinline
-#else
-# define FORCE_INLINE_ATTR
-#endif
-
-#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
-
-
-#ifdef _MSC_VER
-# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
-#endif
+#include "compiler.h"
/* *************************************
* Basic Types
***************************************/
-#ifndef MEM_MODULE
-# define MEM_MODULE
-# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
-# include <stdint.h>
- typedef uint8_t BYTE;
- typedef uint16_t U16;
- typedef uint32_t U32;
- typedef int32_t S32;
- typedef uint64_t U64;
-# else
- typedef unsigned char BYTE;
- typedef unsigned short U16;
- typedef unsigned int U32;
- typedef signed int S32;
- typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */
-# endif
-#endif
-
+#include "mem.h" /* BYTE, U32, U64, size_t */
#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
@@ -161,14 +123,14 @@ static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
static U32 XXH_read32(const void* memPtr)
{
U32 val;
- memcpy(&val, memPtr, sizeof(val));
+ ZSTD_memcpy(&val, memPtr, sizeof(val));
return val;
}
static U64 XXH_read64(const void* memPtr)
{
U64 val;
- memcpy(&val, memPtr, sizeof(val));
+ ZSTD_memcpy(&val, memPtr, sizeof(val));
return val;
}
@@ -305,12 +267,12 @@ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
****************************/
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)
{
- memcpy(dstState, srcState, sizeof(*dstState));
+ ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
}
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)
{
- memcpy(dstState, srcState, sizeof(*dstState));
+ ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
}
@@ -552,12 +514,12 @@ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
{
XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
- memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */
+ ZSTD_memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */
state.v1 = seed + PRIME32_1 + PRIME32_2;
state.v2 = seed + PRIME32_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME32_1;
- memcpy(statePtr, &state, sizeof(state));
+ ZSTD_memcpy(statePtr, &state, sizeof(state));
return XXH_OK;
}
@@ -565,12 +527,12 @@ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int s
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
{
XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
- memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */
+ ZSTD_memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */
state.v1 = seed + PRIME64_1 + PRIME64_2;
state.v2 = seed + PRIME64_2;
state.v3 = seed + 0;
state.v4 = seed - PRIME64_1;
- memcpy(statePtr, &state, sizeof(state));
+ ZSTD_memcpy(statePtr, &state, sizeof(state));
return XXH_OK;
}
@@ -841,14 +803,14 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t
{
XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
- memcpy(dst, &hash, sizeof(*dst));
+ ZSTD_memcpy(dst, &hash, sizeof(*dst));
}
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
{
XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
- memcpy(dst, &hash, sizeof(*dst));
+ ZSTD_memcpy(dst, &hash, sizeof(*dst));
}
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
diff --git a/Utilities/cmzstd/lib/common/xxhash.h b/Utilities/cmzstd/lib/common/xxhash.h
index 4207eba83..16c1f1617 100644
--- a/Utilities/cmzstd/lib/common/xxhash.h
+++ b/Utilities/cmzstd/lib/common/xxhash.h
@@ -1,7 +1,7 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Header File
- * Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - xxHash source repository : https://github.com/Cyan4973/xxHash
@@ -55,7 +55,7 @@ extern "C" {
/* ****************************
* Definitions
******************************/
-#include <stddef.h> /* size_t */
+#include "zstd_deps.h"
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
diff --git a/Utilities/cmzstd/lib/common/zstd_common.c b/Utilities/cmzstd/lib/common/zstd_common.c
index 91fe3323a..3d7e35b30 100644
--- a/Utilities/cmzstd/lib/common/zstd_common.c
+++ b/Utilities/cmzstd/lib/common/zstd_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -13,8 +13,8 @@
/*-*************************************
* Dependencies
***************************************/
-#include <stdlib.h> /* malloc, calloc, free */
-#include <string.h> /* memset */
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
#include "error_private.h"
#include "zstd_internal.h"
@@ -53,31 +53,31 @@ const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString
/*=**************************************************************
* Custom allocator
****************************************************************/
-void* ZSTD_malloc(size_t size, ZSTD_customMem customMem)
+void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)
{
if (customMem.customAlloc)
return customMem.customAlloc(customMem.opaque, size);
- return malloc(size);
+ return ZSTD_malloc(size);
}
-void* ZSTD_calloc(size_t size, ZSTD_customMem customMem)
+void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)
{
if (customMem.customAlloc) {
/* calloc implemented as malloc+memset;
* not as efficient as calloc, but next best guess for custom malloc */
void* const ptr = customMem.customAlloc(customMem.opaque, size);
- memset(ptr, 0, size);
+ ZSTD_memset(ptr, 0, size);
return ptr;
}
- return calloc(1, size);
+ return ZSTD_calloc(1, size);
}
-void ZSTD_free(void* ptr, ZSTD_customMem customMem)
+void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)
{
if (ptr!=NULL) {
if (customMem.customFree)
customMem.customFree(customMem.opaque, ptr);
else
- free(ptr);
+ ZSTD_free(ptr);
}
}
diff --git a/Utilities/cmzstd/lib/common/zstd_deps.h b/Utilities/cmzstd/lib/common/zstd_deps.h
new file mode 100644
index 000000000..14211344a
--- /dev/null
+++ b/Utilities/cmzstd/lib/common/zstd_deps.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* This file provides common libc dependencies that zstd requires.
+ * The purpose is to allow replacing this file with a custom implementation
+ * to compile zstd without libc support.
+ */
+
+/* Need:
+ * NULL
+ * INT_MAX
+ * UINT_MAX
+ * ZSTD_memcpy()
+ * ZSTD_memset()
+ * ZSTD_memmove()
+ */
+#ifndef ZSTD_DEPS_COMMON
+#define ZSTD_DEPS_COMMON
+
+#include <limits.h>
+#include <stddef.h>
+#include <string.h>
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l))
+# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l))
+# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l))
+#else
+# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l))
+# define ZSTD_memmove(d,s,l) memmove((d),(s),(l))
+# define ZSTD_memset(p,v,l) memset((p),(v),(l))
+#endif
+
+#endif /* ZSTD_DEPS_COMMON */
+
+/* Need:
+ * ZSTD_malloc()
+ * ZSTD_free()
+ * ZSTD_calloc()
+ */
+#ifdef ZSTD_DEPS_NEED_MALLOC
+#ifndef ZSTD_DEPS_MALLOC
+#define ZSTD_DEPS_MALLOC
+
+#include <stdlib.h>
+
+#define ZSTD_malloc(s) malloc(s)
+#define ZSTD_calloc(n,s) calloc((n), (s))
+#define ZSTD_free(p) free((p))
+
+#endif /* ZSTD_DEPS_MALLOC */
+#endif /* ZSTD_DEPS_NEED_MALLOC */
+
+/*
+ * Provides 64-bit math support.
+ * Need:
+ * U64 ZSTD_div64(U64 dividend, U32 divisor)
+ */
+#ifdef ZSTD_DEPS_NEED_MATH64
+#ifndef ZSTD_DEPS_MATH64
+#define ZSTD_DEPS_MATH64
+
+#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor))
+
+#endif /* ZSTD_DEPS_MATH64 */
+#endif /* ZSTD_DEPS_NEED_MATH64 */
+
+/* Need:
+ * assert()
+ */
+#ifdef ZSTD_DEPS_NEED_ASSERT
+#ifndef ZSTD_DEPS_ASSERT
+#define ZSTD_DEPS_ASSERT
+
+#include <assert.h>
+
+#endif /* ZSTD_DEPS_ASSERT */
+#endif /* ZSTD_DEPS_NEED_ASSERT */
+
+/* Need:
+ * ZSTD_DEBUG_PRINT()
+ */
+#ifdef ZSTD_DEPS_NEED_IO
+#ifndef ZSTD_DEPS_IO
+#define ZSTD_DEPS_IO
+
+#include <stdio.h>
+#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)
+
+#endif /* ZSTD_DEPS_IO */
+#endif /* ZSTD_DEPS_NEED_IO */
+
+/* Only requested when <stdint.h> is known to be present.
+ * Need:
+ * intptr_t
+ */
+#ifdef ZSTD_DEPS_NEED_STDINT
+#ifndef ZSTD_DEPS_STDINT
+#define ZSTD_DEPS_STDINT
+
+#include <stdint.h>
+
+#endif /* ZSTD_DEPS_STDINT */
+#endif /* ZSTD_DEPS_NEED_STDINT */
diff --git a/Utilities/cmzstd/lib/common/zstd_internal.h b/Utilities/cmzstd/lib/common/zstd_internal.h
index 3bc7e55a0..68252e987 100644
--- a/Utilities/cmzstd/lib/common/zstd_internal.h
+++ b/Utilities/cmzstd/lib/common/zstd_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -19,7 +19,7 @@
/*-*************************************
* Dependencies
***************************************/
-#ifdef __aarch64__
+#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
#include <arm_neon.h>
#endif
#include "compiler.h"
@@ -36,6 +36,11 @@
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
#endif
#include "xxhash.h" /* XXH_reset, update, digest */
+#ifndef ZSTD_NO_TRACE
+# include "zstd_trace.h"
+#else
+# define ZSTD_TRACE 0
+#endif
#if defined (__cplusplus)
extern "C" {
@@ -139,7 +144,7 @@ void _force_has_format_string(const char *format, ...) {
#define ZSTD_REP_NUM 3 /* number of repcodes */
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
-static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
+static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
#define KB *(1 <<10)
#define MB *(1 <<20)
@@ -153,13 +158,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
#define BIT0 1
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
-static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
-static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
+static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
+static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
#define ZSTD_FRAMEIDSIZE 4 /* magic number size */
#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
-static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
+static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
#define ZSTD_FRAMECHECKSUMSIZE 4
@@ -186,61 +191,75 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
#define OffFSELog 8
#define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
-static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 2, 2, 3, 3,
- 4, 6, 7, 8, 9,10,11,12,
- 13,14,15,16 };
-static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 1, 1,
- 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 3, 2, 1, 1, 1, 1, 1,
- -1,-1,-1,-1 };
+#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */
+/* Each table cannot take more than #symbols * FSELog bits */
+#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
+
+static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 3, 3,
+ 4, 6, 7, 8, 9,10,11,12,
+ 13,14,15,16
+};
+static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
+ 4, 3, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 2, 1, 1, 1, 1, 1,
+ -1,-1,-1,-1
+};
#define LL_DEFAULTNORMLOG 6 /* for static allocation */
-static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
-
-static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 2, 2, 3, 3,
- 4, 4, 5, 7, 8, 9,10,11,
- 12,13,14,15,16 };
-static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1,-1,-1,
- -1,-1,-1,-1,-1 };
+static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
+
+static UNUSED_ATTR const U32 ML_bits[MaxML+1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 7, 8, 9,10,11,
+ 12,13,14,15,16
+};
+static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {
+ 1, 4, 3, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1,-1,-1,
+ -1,-1,-1,-1,-1
+};
#define ML_DEFAULTNORMLOG 6 /* for static allocation */
-static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
-
-static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- -1,-1,-1,-1,-1 };
+static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
+
+static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {
+ 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ -1,-1,-1,-1,-1
+};
#define OF_DEFAULTNORMLOG 5 /* for static allocation */
-static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
+static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
/*-*******************************************
* Shared functions to include for inlining
*********************************************/
static void ZSTD_copy8(void* dst, const void* src) {
-#ifdef __aarch64__
+#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));
#else
- memcpy(dst, src, 8);
+ ZSTD_memcpy(dst, src, 8);
#endif
}
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
static void ZSTD_copy16(void* dst, const void* src) {
-#ifdef __aarch64__
+#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
#else
- memcpy(dst, src, 16);
+ ZSTD_memcpy(dst, src, 16);
#endif
}
#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
@@ -255,13 +274,13 @@ typedef enum {
} ZSTD_overlap_e;
/*! ZSTD_wildcopy() :
- * Custom version of memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)
+ * Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)
* @param ovtype controls the overlap detection
* - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
* - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.
* The src buffer must be before the dst buffer.
*/
-MEM_STATIC FORCE_INLINE_ATTR
+MEM_STATIC FORCE_INLINE_ATTR
void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)
{
ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
@@ -284,14 +303,16 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e
* one COPY16() in the first call. Then, do two calls per loop since
* at that point it is more likely to have a high trip count.
*/
-#ifndef __aarch64__
+#ifdef __aarch64__
do {
COPY16(op, ip);
}
while (op < oend);
#else
- COPY16(op, ip);
- if (op >= oend) return;
+ ZSTD_copy16(op, ip);
+ if (16 >= length) return;
+ op += 16;
+ ip += 16;
do {
COPY16(op, ip);
COPY16(op, ip);
@@ -305,7 +326,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src,
{
size_t const length = MIN(dstCapacity, srcSize);
if (length > 0) {
- memcpy(dst, src, length);
+ ZSTD_memcpy(dst, src, length);
}
return length;
}
@@ -320,28 +341,46 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src,
* In which case, resize it down to free some memory */
#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
+/* Controls whether the input/output buffer is buffered or stable. */
+typedef enum {
+ ZSTD_bm_buffered = 0, /* Buffer the input/output */
+ ZSTD_bm_stable = 1 /* ZSTD_inBuffer/ZSTD_outBuffer is stable */
+} ZSTD_bufferMode_e;
+
/*-*******************************************
* Private declarations
*********************************************/
typedef struct seqDef_s {
- U32 offset;
+ U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */
U16 litLength;
U16 matchLength;
} seqDef;
+/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */
+typedef enum {
+ ZSTD_llt_none = 0, /* no longLengthType */
+ ZSTD_llt_literalLength = 1, /* represents a long literal */
+ ZSTD_llt_matchLength = 2 /* represents a long match */
+} ZSTD_longLengthType_e;
+
typedef struct {
seqDef* sequencesStart;
- seqDef* sequences;
+ seqDef* sequences; /* ptr to end of sequences */
BYTE* litStart;
- BYTE* lit;
+ BYTE* lit; /* ptr to end of literals */
BYTE* llCode;
BYTE* mlCode;
BYTE* ofCode;
size_t maxNbSeq;
size_t maxNbLit;
- U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
- U32 longLengthPos;
+
+ /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength
+ * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment
+ * the existing value of the litLength or matchLength by 0x10000.
+ */
+ ZSTD_longLengthType_e longLengthType;
+ U32 longLengthPos; /* Index of the sequence to apply long length modification to */
} seqStore_t;
typedef struct {
@@ -351,7 +390,7 @@ typedef struct {
/**
* Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences
- * indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength.
+ * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength.
*/
MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq)
{
@@ -359,10 +398,10 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore
seqLen.litLength = seq->litLength;
seqLen.matchLength = seq->matchLength + MINMATCH;
if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
- if (seqStore->longLengthID == 1) {
+ if (seqStore->longLengthType == ZSTD_llt_literalLength) {
seqLen.litLength += 0xFFFF;
}
- if (seqStore->longLengthID == 2) {
+ if (seqStore->longLengthType == ZSTD_llt_matchLength) {
seqLen.matchLength += 0xFFFF;
}
}
@@ -384,9 +423,9 @@ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBu
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
/* custom memory allocation functions */
-void* ZSTD_malloc(size_t size, ZSTD_customMem customMem);
-void* ZSTD_calloc(size_t size, ZSTD_customMem customMem);
-void ZSTD_free(void* ptr, ZSTD_customMem customMem);
+void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem);
+void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem);
+void ZSTD_customFree(void* ptr, ZSTD_customMem customMem);
MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */
@@ -394,8 +433,12 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus
assert(val != 0);
{
# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- return _BitScanReverse(&r, val) ? (unsigned)r : 0;
+# if STATIC_BMI2 == 1
+ return _lzcnt_u32(val)^31;
+# else
+ unsigned long r=0;
+ return _BitScanReverse(&r, val) ? (unsigned)r : 0;
+# endif
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
return __builtin_clz (val) ^ 31;
# elif defined(__ICCARM__) /* IAR Intrinsic */
diff --git a/Utilities/cmzstd/lib/common/zstd_trace.h b/Utilities/cmzstd/lib/common/zstd_trace.h
new file mode 100644
index 000000000..485cadf7c
--- /dev/null
+++ b/Utilities/cmzstd/lib/common/zstd_trace.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_TRACE_H
+#define ZSTD_TRACE_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+/* weak symbol support */
+#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && defined(__GNUC__) && \
+ !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \
+ !defined(__CYGWIN__) && !defined(_AIX)
+# define ZSTD_HAVE_WEAK_SYMBOLS 1
+#else
+# define ZSTD_HAVE_WEAK_SYMBOLS 0
+#endif
+#if ZSTD_HAVE_WEAK_SYMBOLS
+# define ZSTD_WEAK_ATTR __attribute__((__weak__))
+#else
+# define ZSTD_WEAK_ATTR
+#endif
+
+/* Only enable tracing when weak symbols are available. */
+#ifndef ZSTD_TRACE
+# define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS
+#endif
+
+#if ZSTD_TRACE
+
+struct ZSTD_CCtx_s;
+struct ZSTD_DCtx_s;
+struct ZSTD_CCtx_params_s;
+
+typedef struct {
+ /**
+ * ZSTD_VERSION_NUMBER
+ *
+ * This is guaranteed to be the first member of ZSTD_trace.
+ * Otherwise, this struct is not stable between versions. If
+ * the version number does not match your expectation, you
+ * should not interpret the rest of the struct.
+ */
+ unsigned version;
+ /**
+ * Non-zero if streaming (de)compression is used.
+ */
+ unsigned streaming;
+ /**
+ * The dictionary ID.
+ */
+ unsigned dictionaryID;
+ /**
+ * Is the dictionary cold?
+ * Only set on decompression.
+ */
+ unsigned dictionaryIsCold;
+ /**
+ * The dictionary size or zero if no dictionary.
+ */
+ size_t dictionarySize;
+ /**
+ * The uncompressed size of the data.
+ */
+ size_t uncompressedSize;
+ /**
+ * The compressed size of the data.
+ */
+ size_t compressedSize;
+ /**
+ * The fully resolved CCtx parameters (NULL on decompression).
+ */
+ struct ZSTD_CCtx_params_s const* params;
+ /**
+ * The ZSTD_CCtx pointer (NULL on decompression).
+ */
+ struct ZSTD_CCtx_s const* cctx;
+ /**
+ * The ZSTD_DCtx pointer (NULL on compression).
+ */
+ struct ZSTD_DCtx_s const* dctx;
+} ZSTD_Trace;
+
+/**
+ * A tracing context. It must be 0 when tracing is disabled.
+ * Otherwise, any non-zero value returned by a tracing begin()
+ * function is presented to any subsequent calls to end().
+ *
+ * Any non-zero value is treated as tracing is enabled and not
+ * interpreted by the library.
+ *
+ * Two possible uses are:
+ * * A timestamp for when the begin() function was called.
+ * * A unique key identifying the (de)compression, like the
+ * address of the [dc]ctx pointer if you need to track
+ * more information than just a timestamp.
+ */
+typedef unsigned long long ZSTD_TraceCtx;
+
+/**
+ * Trace the beginning of a compression call.
+ * @param cctx The dctx pointer for the compression.
+ * It can be used as a key to map begin() to end().
+ * @returns Non-zero if tracing is enabled. The return value is
+ * passed to ZSTD_trace_compress_end().
+ */
+ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin(
+ struct ZSTD_CCtx_s const* cctx);
+
+/**
+ * Trace the end of a compression call.
+ * @param ctx The return value of ZSTD_trace_compress_begin().
+ * @param trace The zstd tracing info.
+ */
+ZSTD_WEAK_ATTR void ZSTD_trace_compress_end(
+ ZSTD_TraceCtx ctx,
+ ZSTD_Trace const* trace);
+
+/**
+ * Trace the beginning of a decompression call.
+ * @param dctx The dctx pointer for the decompression.
+ * It can be used as a key to map begin() to end().
+ * @returns Non-zero if tracing is enabled. The return value is
+ * passed to ZSTD_trace_compress_end().
+ */
+ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin(
+ struct ZSTD_DCtx_s const* dctx);
+
+/**
+ * Trace the end of a decompression call.
+ * @param ctx The return value of ZSTD_trace_decompress_begin().
+ * @param trace The zstd tracing info.
+ */
+ZSTD_WEAK_ATTR void ZSTD_trace_decompress_end(
+ ZSTD_TraceCtx ctx,
+ ZSTD_Trace const* trace);
+
+#endif /* ZSTD_TRACE */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_TRACE_H */
diff --git a/Utilities/cmzstd/lib/compress/fse_compress.c b/Utilities/cmzstd/lib/compress/fse_compress.c
index a42759814..b4297ec88 100644
--- a/Utilities/cmzstd/lib/compress/fse_compress.c
+++ b/Utilities/cmzstd/lib/compress/fse_compress.c
@@ -1,6 +1,6 @@
/* ******************************************************************
* FSE : Finite State Entropy encoder
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -15,8 +15,6 @@
/* **************************************************************
* Includes
****************************************************************/
-#include <stdlib.h> /* malloc, free, qsort */
-#include <string.h> /* memcpy, memset */
#include "../common/compiler.h"
#include "../common/mem.h" /* U32, U16, etc. */
#include "../common/debug.h" /* assert, DEBUGLOG */
@@ -25,6 +23,9 @@
#define FSE_STATIC_LINKING_ONLY
#include "../common/fse.h"
#include "../common/error_private.h"
+#define ZSTD_DEPS_NEED_MALLOC
+#define ZSTD_DEPS_NEED_MATH64
+#include "../common/zstd_deps.h" /* ZSTD_malloc, ZSTD_free, ZSTD_memcpy, ZSTD_memset */
/* **************************************************************
@@ -74,13 +75,15 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
U32 const step = FSE_TABLESTEP(tableSize);
- U32 cumul[FSE_MAX_SYMBOL_VALUE+2];
- FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace;
+ U32* cumul = (U32*)workSpace;
+ FSE_FUNCTION_TYPE* tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSymbolValue + 2));
+
U32 highThreshold = tableSize-1;
+ if ((size_t)workSpace & 3) return ERROR(GENERIC); /* Must be 4 byte aligned */
+ if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge);
/* CTable header */
- if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge);
tableU16[-2] = (U16) tableLog;
tableU16[-1] = (U16) maxSymbolValue;
assert(tableLog < 16); /* required for threshold strategy to work */
@@ -89,7 +92,7 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
* http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
#ifdef __clang_analyzer__
- memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */
+ ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */
#endif
/* symbol start positions */
@@ -168,12 +171,13 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
return 0;
}
-
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
{
FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */
return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol));
}
+#endif
@@ -307,10 +311,10 @@ FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
size_t size;
if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
- return (FSE_CTable*)malloc(size);
+ return (FSE_CTable*)ZSTD_malloc(size);
}
-void FSE_freeCTable (FSE_CTable* ct) { free(ct); }
+void FSE_freeCTable (FSE_CTable* ct) { ZSTD_free(ct); }
/* provides the minimum logSize to safely represent a distribution */
static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
@@ -341,11 +345,10 @@ unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);
}
-
/* Secondary normalization method.
To be used when primary method fails. */
-static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue)
+static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount)
{
short const NOT_YET_ASSIGNED = -2;
U32 s;
@@ -362,7 +365,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
continue;
}
if (count[s] <= lowThreshold) {
- norm[s] = -1;
+ norm[s] = lowProbCount;
distributed++;
total -= count[s];
continue;
@@ -414,7 +417,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
{ U64 const vStepLog = 62 - tableLog;
U64 const mid = (1ULL << (vStepLog-1)) - 1;
- U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */
+ U64 const rStep = ZSTD_div64((((U64)1<<vStepLog) * ToDistribute) + mid, (U32)total); /* scale on remaining */
U64 tmpTotal = mid;
for (s=0; s<=maxSymbolValue; s++) {
if (norm[s]==NOT_YET_ASSIGNED) {
@@ -431,10 +434,9 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
return 0;
}
-
size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
const unsigned* count, size_t total,
- unsigned maxSymbolValue)
+ unsigned maxSymbolValue, unsigned useLowProbCount)
{
/* Sanity checks */
if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;
@@ -443,8 +445,9 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
{ static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
+ short const lowProbCount = useLowProbCount ? -1 : 1;
U64 const scale = 62 - tableLog;
- U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
+ U64 const step = ZSTD_div64((U64)1<<62, (U32)total); /* <== here, one division ! */
U64 const vStep = 1ULL<<(scale-20);
int stillToDistribute = 1<<tableLog;
unsigned s;
@@ -456,7 +459,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
if (count[s] == total) return 0; /* rle special case */
if (count[s] == 0) { normalizedCounter[s]=0; continue; }
if (count[s] <= lowThreshold) {
- normalizedCounter[s] = -1;
+ normalizedCounter[s] = lowProbCount;
stillToDistribute--;
} else {
short proba = (short)((count[s]*step) >> scale);
@@ -470,7 +473,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
} }
if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {
/* corner case, need another normalization method */
- size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);
+ size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount);
if (FSE_isError(errorCode)) return errorCode;
}
else normalizedCounter[largest] += (short)stillToDistribute;
@@ -625,6 +628,7 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize,
size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
/* FSE_compress_wksp() :
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
* `wkspSize` size must be `(1<<tableLog)`.
@@ -643,7 +647,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable));
/* init conditions */
- if (wkspSize < FSE_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge);
+ if (wkspSize < FSE_COMPRESS_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge);
if (srcSize <= 1) return 0; /* Not compressible */
if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
@@ -656,7 +660,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
}
tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue);
- CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) );
+ CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue, /* useLowProbCount */ srcSize >= 2048) );
/* Write table description header */
{ CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );
@@ -678,13 +682,16 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
typedef struct {
FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
- BYTE scratchBuffer[1 << FSE_MAX_TABLELOG];
+ union {
+ U32 hist_wksp[HIST_WKSP_SIZE_U32];
+ BYTE scratchBuffer[1 << FSE_MAX_TABLELOG];
+ } workspace;
} fseWkspMax_t;
size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)
{
fseWkspMax_t scratchBuffer;
- DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */
+ DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_COMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer));
}
@@ -693,6 +700,6 @@ size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcS
{
return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG);
}
-
+#endif
#endif /* FSE_COMMONDEFS_ONLY */
diff --git a/Utilities/cmzstd/lib/compress/hist.c b/Utilities/cmzstd/lib/compress/hist.c
index 61e08c796..073c57e75 100644
--- a/Utilities/cmzstd/lib/compress/hist.c
+++ b/Utilities/cmzstd/lib/compress/hist.c
@@ -1,7 +1,7 @@
/* ******************************************************************
* hist : Histogram functions
* part of Finite State Entropy project
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -34,7 +34,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
unsigned maxSymbolValue = *maxSymbolValuePtr;
unsigned largestCount=0;
- memset(count, 0, (maxSymbolValue+1) * sizeof(*count));
+ ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count));
if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
while (ip<end) {
@@ -60,9 +60,9 @@ typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;
* this design makes better use of OoO cpus,
* and is noticeably faster when some values are heavily repeated.
* But it needs some additional workspace for intermediate tables.
- * `workSpace` size must be a table of size >= HIST_WKSP_SIZE_U32.
+ * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32.
* @return : largest histogram frequency,
- * or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */
+ * or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */
static size_t HIST_count_parallel_wksp(
unsigned* count, unsigned* maxSymbolValuePtr,
const void* source, size_t sourceSize,
@@ -71,22 +71,21 @@ static size_t HIST_count_parallel_wksp(
{
const BYTE* ip = (const BYTE*)source;
const BYTE* const iend = ip+sourceSize;
- unsigned maxSymbolValue = *maxSymbolValuePtr;
+ size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count);
unsigned max=0;
U32* const Counting1 = workSpace;
U32* const Counting2 = Counting1 + 256;
U32* const Counting3 = Counting2 + 256;
U32* const Counting4 = Counting3 + 256;
- memset(workSpace, 0, 4*256*sizeof(unsigned));
-
/* safety checks */
+ assert(*maxSymbolValuePtr <= 255);
if (!sourceSize) {
- memset(count, 0, maxSymbolValue + 1);
+ ZSTD_memset(count, 0, countSize);
*maxSymbolValuePtr = 0;
return 0;
}
- if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
+ ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned));
/* by stripes of 16 bytes */
{ U32 cached = MEM_read32(ip); ip += 4;
@@ -118,21 +117,18 @@ static size_t HIST_count_parallel_wksp(
/* finish last symbols */
while (ip<iend) Counting1[*ip++]++;
- if (check) { /* verify stats will fit into destination table */
- U32 s; for (s=255; s>maxSymbolValue; s--) {
- Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
- if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
- } }
-
{ U32 s;
- if (maxSymbolValue > 255) maxSymbolValue = 255;
- for (s=0; s<=maxSymbolValue; s++) {
- count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
- if (count[s] > max) max = count[s];
+ for (s=0; s<256; s++) {
+ Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
+ if (Counting1[s] > max) max = Counting1[s];
} }
- while (!count[maxSymbolValue]) maxSymbolValue--;
- *maxSymbolValuePtr = maxSymbolValue;
+ { unsigned maxSymbolValue = 255;
+ while (!Counting1[maxSymbolValue]) maxSymbolValue--;
+ if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);
+ *maxSymbolValuePtr = maxSymbolValue;
+ ZSTD_memmove(count, Counting1, countSize); /* in case count & Counting1 are overlapping */
+ }
return (size_t)max;
}
@@ -152,14 +148,6 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);
}
-/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
-size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
- const void* source, size_t sourceSize)
-{
- unsigned tmpCounters[HIST_WKSP_SIZE_U32];
- return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));
-}
-
/* HIST_count_wksp() :
* Same as HIST_count(), but using an externally provided scratch buffer.
* `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */
@@ -175,9 +163,19 @@ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,
return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);
}
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
+/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */
+size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,
+ const void* source, size_t sourceSize)
+{
+ unsigned tmpCounters[HIST_WKSP_SIZE_U32];
+ return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));
+}
+
size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,
const void* src, size_t srcSize)
{
unsigned tmpCounters[HIST_WKSP_SIZE_U32];
return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));
}
+#endif
diff --git a/Utilities/cmzstd/lib/compress/hist.h b/Utilities/cmzstd/lib/compress/hist.h
index 77e3ec4fb..228ed48a7 100644
--- a/Utilities/cmzstd/lib/compress/hist.h
+++ b/Utilities/cmzstd/lib/compress/hist.h
@@ -1,7 +1,7 @@
/* ******************************************************************
* hist : Histogram functions
* part of Finite State Entropy project
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -14,7 +14,7 @@
****************************************************************** */
/* --- dependencies --- */
-#include <stddef.h> /* size_t */
+#include "../common/zstd_deps.h" /* size_t */
/* --- simple histogram functions --- */
diff --git a/Utilities/cmzstd/lib/compress/huf_compress.c b/Utilities/cmzstd/lib/compress/huf_compress.c
index 546879868..485906e67 100644
--- a/Utilities/cmzstd/lib/compress/huf_compress.c
+++ b/Utilities/cmzstd/lib/compress/huf_compress.c
@@ -1,6 +1,6 @@
/* ******************************************************************
* Huffman encoder, part of New Generation Entropy library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -23,8 +23,7 @@
/* **************************************************************
* Includes
****************************************************************/
-#include <string.h> /* memcpy, memset */
-#include <stdio.h> /* printf (debug) */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */
#include "../common/compiler.h"
#include "../common/bitstream.h"
#include "hist.h"
@@ -60,7 +59,15 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
*/
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
-static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
+
+typedef struct {
+ FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
+ U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];
+ unsigned count[HUF_TABLELOG_MAX+1];
+ S16 norm[HUF_TABLELOG_MAX+1];
+} HUF_CompressWeightsWksp;
+
+static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightTable, size_t wtSize, void* workspace, size_t workspaceSize)
{
BYTE* const ostart = (BYTE*) dst;
BYTE* op = ostart;
@@ -68,33 +75,30 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
+ HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)workspace;
- FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
- BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
-
- unsigned count[HUF_TABLELOG_MAX+1];
- S16 norm[HUF_TABLELOG_MAX+1];
+ if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);
/* init conditions */
if (wtSize <= 1) return 0; /* Not compressible */
/* Scan input and build symbol stats */
- { unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */
+ { unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize); /* never fails */
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
}
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
- CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) );
+ CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );
/* Write table description header */
- { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) );
+ { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) );
op += hSize;
}
/* Compress */
- CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );
- { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) );
+ CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) );
+ { CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) );
if (cSize == 0) return 0; /* not enough space for compressed data */
op += cSize;
}
@@ -103,34 +107,33 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
}
-struct HUF_CElt_s {
- U16 val;
- BYTE nbBits;
-}; /* typedef'd to HUF_CElt within "huf.h" */
-
-/*! HUF_writeCTable() :
- `CTable` : Huffman tree to save, using huf representation.
- @return : size of saved CTable */
-size_t HUF_writeCTable (void* dst, size_t maxDstSize,
- const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
-{
+typedef struct {
+ HUF_CompressWeightsWksp wksp;
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
+} HUF_WriteCTableWksp;
+
+size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
+ const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog,
+ void* workspace, size_t workspaceSize)
+{
BYTE* op = (BYTE*)dst;
U32 n;
+ HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)workspace;
- /* check conditions */
+ /* check conditions */
+ if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
/* convert to weight */
- bitsToWeight[0] = 0;
+ wksp->bitsToWeight[0] = 0;
for (n=1; n<huffLog+1; n++)
- bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
+ wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
for (n=0; n<maxSymbolValue; n++)
- huffWeight[n] = bitsToWeight[CTable[n].nbBits];
+ wksp->huffWeight[n] = wksp->bitsToWeight[CTable[n].nbBits];
/* attempt weights compression by FSE */
- { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) );
+ { CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) );
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
op[0] = (BYTE)hSize;
return hSize+1;
@@ -140,12 +143,22 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
- huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
+ wksp->huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
for (n=0; n<maxSymbolValue; n+=2)
- op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
+ op[(n/2)+1] = (BYTE)((wksp->huffWeight[n] << 4) + wksp->huffWeight[n+1]);
return ((maxSymbolValue+1)/2) + 1;
}
+/*! HUF_writeCTable() :
+ `CTable` : Huffman tree to save, using huf representation.
+ @return : size of saved CTable */
+size_t HUF_writeCTable (void* dst, size_t maxDstSize,
+ const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
+{
+ HUF_WriteCTableWksp wksp;
+ return HUF_writeCTable_wksp(dst, maxDstSize, CTable, maxSymbolValue, huffLog, &wksp, sizeof(wksp));
+}
+
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)
{
@@ -156,6 +169,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
/* get symbol weights */
CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));
+ *hasZeroWeights = (rankVal[0] > 0);
/* check result */
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
@@ -164,16 +178,14 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
/* Prepare base value per rank */
{ U32 n, nextRankStart = 0;
for (n=1; n<=tableLog; n++) {
- U32 current = nextRankStart;
+ U32 curr = nextRankStart;
nextRankStart += (rankVal[n] << (n-1));
- rankVal[n] = current;
+ rankVal[n] = curr;
} }
/* fill nbBits */
- *hasZeroWeights = 0;
{ U32 n; for (n=0; n<nbSymbols; n++) {
const U32 w = huffWeight[n];
- *hasZeroWeights |= (w == 0);
CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0);
} }
@@ -212,32 +224,63 @@ typedef struct nodeElt_s {
BYTE nbBits;
} nodeElt;
+/**
+ * HUF_setMaxHeight():
+ * Enforces maxNbBits on the Huffman tree described in huffNode.
+ *
+ * It sets all nodes with nbBits > maxNbBits to be maxNbBits. Then it adjusts
+ * the tree to so that it is a valid canonical Huffman tree.
+ *
+ * @pre The sum of the ranks of each symbol == 2^largestBits,
+ * where largestBits == huffNode[lastNonNull].nbBits.
+ * @post The sum of the ranks of each symbol == 2^largestBits,
+ * where largestBits is the return value <= maxNbBits.
+ *
+ * @param huffNode The Huffman tree modified in place to enforce maxNbBits.
+ * @param lastNonNull The symbol with the lowest count in the Huffman tree.
+ * @param maxNbBits The maximum allowed number of bits, which the Huffman tree
+ * may not respect. After this function the Huffman tree will
+ * respect maxNbBits.
+ * @return The maximum number of bits of the Huffman tree after adjustment,
+ * necessarily no more than maxNbBits.
+ */
static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
{
const U32 largestBits = huffNode[lastNonNull].nbBits;
- if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */
+ /* early exit : no elt > maxNbBits, so the tree is already valid. */
+ if (largestBits <= maxNbBits) return largestBits;
/* there are several too large elements (at least >= 2) */
{ int totalCost = 0;
const U32 baseCost = 1 << (largestBits - maxNbBits);
int n = (int)lastNonNull;
+ /* Adjust any ranks > maxNbBits to maxNbBits.
+ * Compute totalCost, which is how far the sum of the ranks is
+ * we are over 2^largestBits after adjust the offending ranks.
+ */
while (huffNode[n].nbBits > maxNbBits) {
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
huffNode[n].nbBits = (BYTE)maxNbBits;
- n --;
- } /* n stops at huffNode[n].nbBits <= maxNbBits */
- while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */
+ n--;
+ }
+ /* n stops at huffNode[n].nbBits <= maxNbBits */
+ assert(huffNode[n].nbBits <= maxNbBits);
+ /* n end at index of smallest symbol using < maxNbBits */
+ while (huffNode[n].nbBits == maxNbBits) --n;
- /* renorm totalCost */
- totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */
+ /* renorm totalCost from 2^largestBits to 2^maxNbBits
+ * note : totalCost is necessarily a multiple of baseCost */
+ assert((totalCost & (baseCost - 1)) == 0);
+ totalCost >>= (largestBits - maxNbBits);
+ assert(totalCost > 0);
/* repay normalized cost */
{ U32 const noSymbol = 0xF0F0F0F0;
U32 rankLast[HUF_TABLELOG_MAX+2];
- /* Get pos of last (smallest) symbol per rank */
- memset(rankLast, 0xF0, sizeof(rankLast));
+ /* Get pos of last (smallest = lowest cum. count) symbol per rank */
+ ZSTD_memset(rankLast, 0xF0, sizeof(rankLast));
{ U32 currentNbBits = maxNbBits;
int pos;
for (pos=n ; pos >= 0; pos--) {
@@ -247,34 +290,65 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
} }
while (totalCost > 0) {
+ /* Try to reduce the next power of 2 above totalCost because we
+ * gain back half the rank.
+ */
U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1;
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {
U32 const highPos = rankLast[nBitsToDecrease];
U32 const lowPos = rankLast[nBitsToDecrease-1];
if (highPos == noSymbol) continue;
+ /* Decrease highPos if no symbols of lowPos or if it is
+ * not cheaper to remove 2 lowPos than highPos.
+ */
if (lowPos == noSymbol) break;
{ U32 const highTotal = huffNode[highPos].count;
U32 const lowTotal = 2 * huffNode[lowPos].count;
if (highTotal <= lowTotal) break;
} }
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
+ assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1);
/* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))
- nBitsToDecrease ++;
+ nBitsToDecrease++;
+ assert(rankLast[nBitsToDecrease] != noSymbol);
+ /* Increase the number of bits to gain back half the rank cost. */
totalCost -= 1 << (nBitsToDecrease-1);
+ huffNode[rankLast[nBitsToDecrease]].nbBits++;
+
+ /* Fix up the new rank.
+ * If the new rank was empty, this symbol is now its smallest.
+ * Otherwise, this symbol will be the largest in the new rank so no adjustment.
+ */
if (rankLast[nBitsToDecrease-1] == noSymbol)
- rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */
- huffNode[rankLast[nBitsToDecrease]].nbBits ++;
+ rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];
+ /* Fix up the old rank.
+ * If the symbol was at position 0, meaning it was the highest weight symbol in the tree,
+ * it must be the only symbol in its rank, so the old rank now has no symbols.
+ * Otherwise, since the Huffman nodes are sorted by count, the previous position is now
+ * the smallest node in the rank. If the previous position belongs to a different rank,
+ * then the rank is now empty.
+ */
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */
rankLast[nBitsToDecrease] = noSymbol;
else {
rankLast[nBitsToDecrease]--;
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
- } } /* while (totalCost > 0) */
-
+ }
+ } /* while (totalCost > 0) */
+
+ /* If we've removed too much weight, then we have to add it back.
+ * To avoid overshooting again, we only adjust the smallest rank.
+ * We take the largest nodes from the lowest rank 0 and move them
+ * to rank 1. There's guaranteed to be enough rank 0 symbols because
+ * TODO.
+ */
while (totalCost < 0) { /* Sometimes, cost correction overshoot */
- if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */
+ /* special case : no rank 1 symbol (using maxNbBits-1);
+ * let's create one from largest rank 0 (using maxNbBits).
+ */
+ if (rankLast[1] == noSymbol) {
while (huffNode[n].nbBits == maxNbBits) n--;
huffNode[n+1].nbBits--;
assert(n >= 0);
@@ -285,14 +359,16 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
huffNode[ rankLast[1] + 1 ].nbBits--;
rankLast[1]++;
totalCost ++;
- } } } /* there are several too large elements (at least >= 2) */
+ }
+ } /* repay normalized cost */
+ } /* there are several too large elements (at least >= 2) */
return maxNbBits;
}
typedef struct {
U32 base;
- U32 current;
+ U32 curr;
} rankPos;
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
@@ -304,21 +380,45 @@ typedef struct {
rankPos rankPosition[RANK_POSITION_TABLE_SIZE];
} HUF_buildCTable_wksp_tables;
+/**
+ * HUF_sort():
+ * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order.
+ *
+ * @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled.
+ * Must have (maxSymbolValue + 1) entries.
+ * @param[in] count Histogram of the symbols.
+ * @param[in] maxSymbolValue Maximum symbol value.
+ * @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries.
+ */
static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition)
{
- U32 n;
-
- memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);
- for (n=0; n<=maxSymbolValue; n++) {
- U32 r = BIT_highbit32(count[n] + 1);
- rankPosition[r].base ++;
+ int n;
+ int const maxSymbolValue1 = (int)maxSymbolValue + 1;
+
+ /* Compute base and set curr to base.
+ * For symbol s let lowerRank = BIT_highbit32(count[n]+1) and rank = lowerRank + 1.
+ * Then 2^lowerRank <= count[n]+1 <= 2^rank.
+ * We attribute each symbol to lowerRank's base value, because we want to know where
+ * each rank begins in the output, so for rank R we want to count ranks R+1 and above.
+ */
+ ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);
+ for (n = 0; n < maxSymbolValue1; ++n) {
+ U32 lowerRank = BIT_highbit32(count[n] + 1);
+ rankPosition[lowerRank].base++;
}
- for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base;
- for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base;
- for (n=0; n<=maxSymbolValue; n++) {
+ assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0);
+ for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) {
+ rankPosition[n-1].base += rankPosition[n].base;
+ rankPosition[n-1].curr = rankPosition[n-1].base;
+ }
+ /* Sort */
+ for (n = 0; n < maxSymbolValue1; ++n) {
U32 const c = count[n];
U32 const r = BIT_highbit32(c+1) + 1;
- U32 pos = rankPosition[r].current++;
+ U32 pos = rankPosition[r].curr++;
+ /* Insert into the correct position in the rank.
+ * We have at most 256 symbols, so this insertion should be fine.
+ */
while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) {
huffNode[pos] = huffNode[pos-1];
pos--;
@@ -335,28 +435,20 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu
*/
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)
-size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
+/* HUF_buildTree():
+ * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree.
+ *
+ * @param huffNode The array sorted by HUF_sort(). Builds the Huffman tree in this array.
+ * @param maxSymbolValue The maximum symbol value.
+ * @return The smallest node in the Huffman tree (by count).
+ */
+static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue)
{
- HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace;
- nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;
- nodeElt* const huffNode = huffNode0+1;
+ nodeElt* const huffNode0 = huffNode - 1;
int nonNullRank;
int lowS, lowN;
int nodeNb = STARTNODE;
int n, nodeRoot;
-
- /* safety checks */
- if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
- if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))
- return ERROR(workSpace_tooSmall);
- if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
- if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)
- return ERROR(maxSymbolValue_tooLarge);
- memset(huffNode0, 0, sizeof(huffNodeTable));
-
- /* sort, decreasing order */
- HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);
-
/* init for parents */
nonNullRank = (int)maxSymbolValue;
while(huffNode[nonNullRank].count == 0) nonNullRank--;
@@ -383,42 +475,72 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo
for (n=0; n<=nonNullRank; n++)
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;
+ return nonNullRank;
+}
+
+/**
+ * HUF_buildCTableFromTree():
+ * Build the CTable given the Huffman tree in huffNode.
+ *
+ * @param[out] CTable The output Huffman CTable.
+ * @param huffNode The Huffman tree.
+ * @param nonNullRank The last and smallest node in the Huffman tree.
+ * @param maxSymbolValue The maximum symbol value.
+ * @param maxNbBits The exact maximum number of bits used in the Huffman tree.
+ */
+static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits)
+{
+ /* fill result into ctable (val, nbBits) */
+ int n;
+ U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
+ U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};
+ int const alphabetSize = (int)(maxSymbolValue + 1);
+ for (n=0; n<=nonNullRank; n++)
+ nbPerRank[huffNode[n].nbBits]++;
+ /* determine starting value per rank */
+ { U16 min = 0;
+ for (n=(int)maxNbBits; n>0; n--) {
+ valPerRank[n] = min; /* get starting value within each rank */
+ min += nbPerRank[n];
+ min >>= 1;
+ } }
+ for (n=0; n<alphabetSize; n++)
+ CTable[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
+ for (n=0; n<alphabetSize; n++)
+ CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */
+}
+
+size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
+{
+ HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace;
+ nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;
+ nodeElt* const huffNode = huffNode0+1;
+ int nonNullRank;
+
+ /* safety checks */
+ if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
+ if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))
+ return ERROR(workSpace_tooSmall);
+ if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
+ if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)
+ return ERROR(maxSymbolValue_tooLarge);
+ ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable));
+
+ /* sort, decreasing order */
+ HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);
+
+ /* build tree */
+ nonNullRank = HUF_buildTree(huffNode, maxSymbolValue);
+
/* enforce maxTableLog */
maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);
+ if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
- /* fill result into tree (val, nbBits) */
- { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
- U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};
- int const alphabetSize = (int)(maxSymbolValue + 1);
- if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
- for (n=0; n<=nonNullRank; n++)
- nbPerRank[huffNode[n].nbBits]++;
- /* determine stating value per rank */
- { U16 min = 0;
- for (n=(int)maxNbBits; n>0; n--) {
- valPerRank[n] = min; /* get starting value within each rank */
- min += nbPerRank[n];
- min >>= 1;
- } }
- for (n=0; n<alphabetSize; n++)
- tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
- for (n=0; n<alphabetSize; n++)
- tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */
- }
+ HUF_buildCTableFromTree(tree, huffNode, nonNullRank, maxSymbolValue, maxNbBits);
return maxNbBits;
}
-/** HUF_buildCTable() :
- * @return : maxNbBits
- * Note : count is used before tree is written, so they can safely overlap
- */
-size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
-{
- HUF_buildCTable_wksp_tables workspace;
- return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace));
-}
-
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
{
size_t nbBits = 0;
@@ -629,29 +751,33 @@ static size_t HUF_compressCTable_internal(
typedef struct {
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
- HUF_buildCTable_wksp_tables buildCTable_wksp;
+ union {
+ HUF_buildCTable_wksp_tables buildCTable_wksp;
+ HUF_WriteCTableWksp writeCTable_wksp;
+ } wksps;
} HUF_compress_tables_t;
/* HUF_compress_internal() :
- * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
+ * `workSpace_align4` must be aligned on 4-bytes boundaries,
+ * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U32 unsigned */
static size_t
HUF_compress_internal (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
HUF_nbStreams_e nbStreams,
- void* workSpace, size_t wkspSize,
+ void* workSpace_align4, size_t wkspSize,
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
const int bmi2)
{
- HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;
+ HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace_align4;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE);
+ assert(((size_t)workSpace_align4 & 3) == 0); /* must be aligned on 4-bytes boundaries */
/* checks & inits */
- if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);
if (!srcSize) return 0; /* Uncompressed */
if (!dstSize) return 0; /* cannot fit anything within dst budget */
@@ -669,7 +795,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
}
/* Scan input and build symbol stats */
- { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) );
+ { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace_align4, wkspSize) );
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
}
@@ -691,16 +817,17 @@ HUF_compress_internal (void* dst, size_t dstSize,
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
maxSymbolValue, huffLog,
- &table->buildCTable_wksp, sizeof(table->buildCTable_wksp));
+ &table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));
CHECK_F(maxBits);
huffLog = (U32)maxBits;
/* Zero unused symbols in CTable, so we can check it for validity */
- memset(table->CTable + (maxSymbolValue + 1), 0,
+ ZSTD_memset(table->CTable + (maxSymbolValue + 1), 0,
sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
}
/* Write table description header */
- { CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );
+ { CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog,
+ &table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) );
/* Check if using previous huffman table is beneficial */
if (repeat && *repeat != HUF_repeat_none) {
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
@@ -716,7 +843,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
op += hSize;
if (repeat) { *repeat = HUF_repeat_none; }
if (oldHufTable)
- memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
+ ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */
}
return HUF_compressCTable_internal(ostart, op, oend,
src, srcSize,
@@ -747,14 +874,6 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
repeat, preferRepeat, bmi2);
}
-size_t HUF_compress1X (void* dst, size_t dstSize,
- const void* src, size_t srcSize,
- unsigned maxSymbolValue, unsigned huffLog)
-{
- unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
- return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
-}
-
/* HUF_compress4X_repeat():
* compress input using 4 streams.
* provide workspace to generate compression tables */
@@ -784,6 +903,25 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
hufTable, repeat, preferRepeat, bmi2);
}
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
+/** HUF_buildCTable() :
+ * @return : maxNbBits
+ * Note : count is used before tree is written, so they can safely overlap
+ */
+size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
+{
+ HUF_buildCTable_wksp_tables workspace;
+ return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace));
+}
+
+size_t HUF_compress1X (void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned huffLog)
+{
+ unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
+ return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
+}
+
size_t HUF_compress2 (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
@@ -796,3 +934,4 @@ size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSi
{
return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
}
+#endif
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress.c b/Utilities/cmzstd/lib/compress/zstd_compress.c
index 3f963b1cf..b7ee2980a 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress.c
+++ b/Utilities/cmzstd/lib/compress/zstd_compress.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -11,8 +11,7 @@
/*-*************************************
* Dependencies
***************************************/
-#include <limits.h> /* INT_MAX */
-#include <string.h> /* memset */
+#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
#include "../common/cpu.h"
#include "../common/mem.h"
#include "hist.h" /* HIST_countFast_wksp */
@@ -30,6 +29,19 @@
#include "zstd_ldm.h"
#include "zstd_compress_superblock.h"
+/* ***************************************************************
+* Tuning parameters
+*****************************************************************/
+/*!
+ * COMPRESS_HEAPMODE :
+ * Select how default decompression function ZSTD_compress() allocates its context,
+ * on stack (0, default), or into heap (1).
+ * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected.
+ */
+#ifndef ZSTD_COMPRESS_HEAPMODE
+# define ZSTD_COMPRESS_HEAPMODE 0
+#endif
+
/*-*************************************
* Helper functions
@@ -52,6 +64,7 @@ size_t ZSTD_compressBound(size_t srcSize) {
struct ZSTD_CDict_s {
const void* dictContent;
size_t dictContentSize;
+ ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */
U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
ZSTD_cwksp workspace;
ZSTD_matchState_t matchState;
@@ -59,6 +72,10 @@ struct ZSTD_CDict_s {
ZSTD_customMem customMem;
U32 dictID;
int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use
+ * row-based matchfinder. Unless the cdict is reloaded, we will use
+ * the same greedy/lazy matchfinder at compression time.
+ */
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -69,7 +86,7 @@ ZSTD_CCtx* ZSTD_createCCtx(void)
static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
{
assert(cctx != NULL);
- memset(cctx, 0, sizeof(*cctx));
+ ZSTD_memset(cctx, 0, sizeof(*cctx));
cctx->customMem = memManager;
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
{ size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
@@ -82,8 +99,8 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
{
ZSTD_STATIC_ASSERT(zcss_init==0);
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
- { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
+ { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);
if (!cctx) return NULL;
ZSTD_initCCtx(cctx, customMem);
return cctx;
@@ -96,20 +113,20 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
ZSTD_CCtx* cctx;
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
- ZSTD_cwksp_init(&ws, workspace, workspaceSize);
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));
if (cctx == NULL) return NULL;
- memset(cctx, 0, sizeof(ZSTD_CCtx));
+ ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));
ZSTD_cwksp_move(&cctx->workspace, &ws);
cctx->staticSize = workspaceSize;
/* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */
- if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
+ if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;
cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));
- cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE);
+ cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE);
cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
return cctx;
}
@@ -119,10 +136,10 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)
*/
static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)
{
- ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem);
+ ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);
ZSTD_freeCDict(cctx->localDict.cdict);
- memset(&cctx->localDict, 0, sizeof(cctx->localDict));
- memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
+ ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));
+ ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));
cctx->cdict = NULL;
}
@@ -153,7 +170,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);
ZSTD_freeCCtxContent(cctx);
if (!cctxInWorkspace) {
- ZSTD_free(cctx, cctx->customMem);
+ ZSTD_customFree(cctx, cctx->customMem);
}
}
return 0;
@@ -189,15 +206,90 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
/* private API call, for dictBuilder only */
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
+/* Returns true if the strategy supports using a row based matchfinder */
+static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) {
+ return (strategy >= ZSTD_greedy && strategy <= ZSTD_lazy2);
+}
+
+/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder
+ * for this compression.
+ */
+static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_useRowMatchFinderMode_e mode) {
+ assert(mode != ZSTD_urm_auto);
+ return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_urm_enableRowMatchFinder);
+}
+
+/* Returns row matchfinder usage enum given an initial mode and cParams */
+static ZSTD_useRowMatchFinderMode_e ZSTD_resolveRowMatchFinderMode(ZSTD_useRowMatchFinderMode_e mode,
+ const ZSTD_compressionParameters* const cParams) {
+#if !defined(ZSTD_NO_INTRINSICS) && (defined(__SSE2__) || defined(__ARM_NEON))
+ int const kHasSIMD128 = 1;
+#else
+ int const kHasSIMD128 = 0;
+#endif
+ if (mode != ZSTD_urm_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */
+ mode = ZSTD_urm_disableRowMatchFinder;
+ if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode;
+ if (kHasSIMD128) {
+ if (cParams->windowLog > 14) mode = ZSTD_urm_enableRowMatchFinder;
+ } else {
+ if (cParams->windowLog > 17) mode = ZSTD_urm_enableRowMatchFinder;
+ }
+ return mode;
+}
+
+/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */
+static int ZSTD_allocateChainTable(const ZSTD_strategy strategy,
+ const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const U32 forDDSDict) {
+ assert(useRowMatchFinder != ZSTD_urm_auto);
+ /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate.
+ * We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder.
+ */
+ return forDDSDict || ((strategy != ZSTD_fast) && !ZSTD_rowMatchFinderUsed(strategy, useRowMatchFinder));
+}
+
+/* Returns 1 if compression parameters are such that we should
+ * enable long distance matching (wlog >= 27, strategy >= btopt).
+ * Returns 0 otherwise.
+ */
+static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) {
+ return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27;
+}
+
+/* Returns 1 if compression parameters are such that we should
+ * enable blockSplitter (wlog >= 17, strategy >= btopt).
+ * Returns 0 otherwise.
+ */
+static U32 ZSTD_CParams_useBlockSplitter(const ZSTD_compressionParameters* const cParams) {
+ return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17;
+}
+
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
ZSTD_compressionParameters cParams)
{
ZSTD_CCtx_params cctxParams;
- memset(&cctxParams, 0, sizeof(cctxParams));
+ /* should not matter, as all cParams are presumed properly defined */
+ ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);
cctxParams.cParams = cParams;
- cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
+
+ /* Adjust advanced params according to cParams */
+ if (ZSTD_CParams_shouldEnableLdm(&cParams)) {
+ DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params");
+ cctxParams.ldmParams.enableLdm = 1;
+ /* LDM is enabled by default for optimal parser and window size >= 128MB */
+ ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);
+ assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);
+ assert(cctxParams.ldmParams.hashRateLog < 32);
+ }
+
+ if (ZSTD_CParams_useBlockSplitter(&cParams)) {
+ DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including block splitting into cctx params");
+ cctxParams.splitBlocks = 1;
+ }
+
+ cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);
assert(!ZSTD_checkCParams(cParams));
- cctxParams.fParams.contentSizeFlag = 1;
return cctxParams;
}
@@ -205,13 +297,12 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(
ZSTD_customMem customMem)
{
ZSTD_CCtx_params* params;
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
- params = (ZSTD_CCtx_params*)ZSTD_calloc(
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
+ params = (ZSTD_CCtx_params*)ZSTD_customCalloc(
sizeof(ZSTD_CCtx_params), customMem);
if (!params) { return NULL; }
+ ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);
params->customMem = customMem;
- params->compressionLevel = ZSTD_CLEVEL_DEFAULT;
- params->fParams.contentSizeFlag = 1;
return params;
}
@@ -223,7 +314,7 @@ ZSTD_CCtx_params* ZSTD_createCCtxParams(void)
size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)
{
if (params == NULL) { return 0; }
- ZSTD_free(params, params->customMem);
+ ZSTD_customFree(params, params->customMem);
return 0;
}
@@ -234,35 +325,54 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)
size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
- memset(cctxParams, 0, sizeof(*cctxParams));
+ ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
cctxParams->compressionLevel = compressionLevel;
cctxParams->fParams.contentSizeFlag = 1;
return 0;
}
+#define ZSTD_NO_CLEVEL 0
+
+/**
+ * Initializes the cctxParams from params and compressionLevel.
+ * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.
+ */
+static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel)
+{
+ assert(!ZSTD_checkCParams(params->cParams));
+ ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
+ cctxParams->cParams = params->cParams;
+ cctxParams->fParams = params->fParams;
+ /* Should not matter, as all cParams are presumed properly defined.
+ * But, set it for tracing anyway.
+ */
+ cctxParams->compressionLevel = compressionLevel;
+ cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &params->cParams);
+ DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d", cctxParams->useRowMatchFinder);
+}
+
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
{
RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!");
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
- memset(cctxParams, 0, sizeof(*cctxParams));
- assert(!ZSTD_checkCParams(params.cParams));
- cctxParams->cParams = params.cParams;
- cctxParams->fParams = params.fParams;
- cctxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
+ ZSTD_CCtxParams_init_internal(cctxParams, &params, ZSTD_NO_CLEVEL);
return 0;
}
-/* ZSTD_assignParamsToCCtxParams() :
- * params is presumed valid at this stage */
-static ZSTD_CCtx_params ZSTD_assignParamsToCCtxParams(
- const ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
+/**
+ * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.
+ * @param param Validated zstd parameters.
+ */
+static void ZSTD_CCtxParams_setZstdParams(
+ ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
{
- ZSTD_CCtx_params ret = *cctxParams;
assert(!ZSTD_checkCParams(params->cParams));
- ret.cParams = params->cParams;
- ret.fParams = params->fParams;
- ret.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */
- return ret;
+ cctxParams->cParams = params->cParams;
+ cctxParams->fParams = params->fParams;
+ /* Should not matter, as all cParams are presumed properly defined.
+ * But, set it for tracing anyway.
+ */
+ cctxParams->compressionLevel = ZSTD_NO_CLEVEL;
}
ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
@@ -354,6 +464,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
#endif
return bounds;
+ case ZSTD_c_enableDedicatedDictSearch:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
case ZSTD_c_enableLongDistanceMatching:
bounds.lowerBound = 0;
bounds.upperBound = 1;
@@ -397,7 +512,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
return bounds;
case ZSTD_c_forceAttachDict:
- ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy);
+ ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);
bounds.lowerBound = ZSTD_dictDefaultAttach;
bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */
return bounds;
@@ -418,6 +533,37 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;
return bounds;
+ case ZSTD_c_stableInBuffer:
+ case ZSTD_c_stableOutBuffer:
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
+ bounds.upperBound = (int)ZSTD_bm_stable;
+ return bounds;
+
+ case ZSTD_c_blockDelimiters:
+ bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;
+ bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;
+ return bounds;
+
+ case ZSTD_c_validateSequences:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_splitBlocks:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
+ case ZSTD_c_useRowMatchFinder:
+ bounds.lowerBound = (int)ZSTD_urm_auto;
+ bounds.upperBound = (int)ZSTD_urm_enableRowMatchFinder;
+ return bounds;
+
+ case ZSTD_c_deterministicRefPrefix:
+ bounds.lowerBound = 0;
+ bounds.upperBound = 1;
+ return bounds;
+
default:
bounds.error = ERROR(parameter_unsupported);
return bounds;
@@ -465,6 +611,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
case ZSTD_c_jobSize:
case ZSTD_c_overlapLog:
case ZSTD_c_rsyncable:
+ case ZSTD_c_enableDedicatedDictSearch:
case ZSTD_c_enableLongDistanceMatching:
case ZSTD_c_ldmHashLog:
case ZSTD_c_ldmMinMatch:
@@ -474,6 +621,13 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
case ZSTD_c_literalCompressionMode:
case ZSTD_c_targetCBlockSize:
case ZSTD_c_srcSizeHint:
+ case ZSTD_c_stableInBuffer:
+ case ZSTD_c_stableOutBuffer:
+ case ZSTD_c_blockDelimiters:
+ case ZSTD_c_validateSequences:
+ case ZSTD_c_splitBlocks:
+ case ZSTD_c_useRowMatchFinder:
+ case ZSTD_c_deterministicRefPrefix:
default:
return 0;
}
@@ -515,12 +669,20 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
case ZSTD_c_jobSize:
case ZSTD_c_overlapLog:
case ZSTD_c_rsyncable:
+ case ZSTD_c_enableDedicatedDictSearch:
case ZSTD_c_enableLongDistanceMatching:
case ZSTD_c_ldmHashLog:
case ZSTD_c_ldmMinMatch:
case ZSTD_c_ldmBucketSizeLog:
case ZSTD_c_targetCBlockSize:
case ZSTD_c_srcSizeHint:
+ case ZSTD_c_stableInBuffer:
+ case ZSTD_c_stableOutBuffer:
+ case ZSTD_c_blockDelimiters:
+ case ZSTD_c_validateSequences:
+ case ZSTD_c_splitBlocks:
+ case ZSTD_c_useRowMatchFinder:
+ case ZSTD_c_deterministicRefPrefix:
break;
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
@@ -541,9 +703,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
case ZSTD_c_compressionLevel : {
FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), "");
- if (value) { /* 0 : does not change current level */
+ if (value == 0)
+ CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
+ else
CCtxParams->compressionLevel = value;
- }
if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;
return 0; /* return type (size_t) cannot represent negative values */
}
@@ -667,6 +830,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
return CCtxParams->rsyncable;
#endif
+ case ZSTD_c_enableDedicatedDictSearch :
+ CCtxParams->enableDedicatedDictSearch = (value!=0);
+ return CCtxParams->enableDedicatedDictSearch;
+
case ZSTD_c_enableLongDistanceMatching :
CCtxParams->ldmParams.enableLdm = (value!=0);
return CCtxParams->ldmParams.enableLdm;
@@ -707,17 +874,52 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
CCtxParams->srcSizeHint = value;
return CCtxParams->srcSizeHint;
+ case ZSTD_c_stableInBuffer:
+ BOUNDCHECK(ZSTD_c_stableInBuffer, value);
+ CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;
+ return CCtxParams->inBufferMode;
+
+ case ZSTD_c_stableOutBuffer:
+ BOUNDCHECK(ZSTD_c_stableOutBuffer, value);
+ CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;
+ return CCtxParams->outBufferMode;
+
+ case ZSTD_c_blockDelimiters:
+ BOUNDCHECK(ZSTD_c_blockDelimiters, value);
+ CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value;
+ return CCtxParams->blockDelimiters;
+
+ case ZSTD_c_validateSequences:
+ BOUNDCHECK(ZSTD_c_validateSequences, value);
+ CCtxParams->validateSequences = value;
+ return CCtxParams->validateSequences;
+
+ case ZSTD_c_splitBlocks:
+ BOUNDCHECK(ZSTD_c_splitBlocks, value);
+ CCtxParams->splitBlocks = value;
+ return CCtxParams->splitBlocks;
+
+ case ZSTD_c_useRowMatchFinder:
+ BOUNDCHECK(ZSTD_c_useRowMatchFinder, value);
+ CCtxParams->useRowMatchFinder = (ZSTD_useRowMatchFinderMode_e)value;
+ return CCtxParams->useRowMatchFinder;
+
+ case ZSTD_c_deterministicRefPrefix:
+ BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value);
+ CCtxParams->deterministicRefPrefix = !!value;
+ return CCtxParams->deterministicRefPrefix;
+
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
}
}
-size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value)
+size_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)
{
return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);
}
size_t ZSTD_CCtxParams_getParameter(
- ZSTD_CCtx_params* CCtxParams, ZSTD_cParameter param, int* value)
+ ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)
{
switch(param)
{
@@ -794,6 +996,9 @@ size_t ZSTD_CCtxParams_getParameter(
*value = CCtxParams->rsyncable;
break;
#endif
+ case ZSTD_c_enableDedicatedDictSearch :
+ *value = CCtxParams->enableDedicatedDictSearch;
+ break;
case ZSTD_c_enableLongDistanceMatching :
*value = CCtxParams->ldmParams.enableLdm;
break;
@@ -815,6 +1020,27 @@ size_t ZSTD_CCtxParams_getParameter(
case ZSTD_c_srcSizeHint :
*value = (int)CCtxParams->srcSizeHint;
break;
+ case ZSTD_c_stableInBuffer :
+ *value = (int)CCtxParams->inBufferMode;
+ break;
+ case ZSTD_c_stableOutBuffer :
+ *value = (int)CCtxParams->outBufferMode;
+ break;
+ case ZSTD_c_blockDelimiters :
+ *value = (int)CCtxParams->blockDelimiters;
+ break;
+ case ZSTD_c_validateSequences :
+ *value = (int)CCtxParams->validateSequences;
+ break;
+ case ZSTD_c_splitBlocks :
+ *value = (int)CCtxParams->splitBlocks;
+ break;
+ case ZSTD_c_useRowMatchFinder :
+ *value = (int)CCtxParams->useRowMatchFinder;
+ break;
+ case ZSTD_c_deterministicRefPrefix:
+ *value = (int)CCtxParams->deterministicRefPrefix;
+ break;
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
}
return 0;
@@ -850,6 +1076,14 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
return 0;
}
+static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(
+ int const compressionLevel,
+ size_t const dictSize);
+static int ZSTD_dedicatedDictSearch_isSupported(
+ const ZSTD_compressionParameters* cParams);
+static void ZSTD_dedicatedDictSearch_revertCParams(
+ ZSTD_compressionParameters* cParams);
+
/**
* Initializes the local dict using the requested parameters.
* NOTE: This does not use the pledged src size, because it may be used for more
@@ -858,8 +1092,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo
static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
{
ZSTD_localDict* const dl = &cctx->localDict;
- ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams(
- &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize);
if (dl->dict == NULL) {
/* No local dictionary. */
assert(dl->dictBuffer == NULL);
@@ -876,12 +1108,12 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)
assert(cctx->cdict == NULL);
assert(cctx->prefixDict.dict == NULL);
- dl->cdict = ZSTD_createCDict_advanced(
+ dl->cdict = ZSTD_createCDict_advanced2(
dl->dict,
dl->dictSize,
ZSTD_dlm_byRef,
dl->dictContentType,
- cParams,
+ &cctx->requestedParams,
cctx->customMem);
RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed");
cctx->cdict = dl->cdict;
@@ -894,8 +1126,6 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
{
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
"Can't load a dictionary when ctx is not in init stage.");
- RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
- "no malloc for static CCtx");
DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize);
ZSTD_clearAllDicts(cctx); /* in case one already exists */
if (dict == NULL || dictSize == 0) /* no dictionary mode */
@@ -903,9 +1133,12 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
if (dictLoadMethod == ZSTD_dlm_byRef) {
cctx->localDict.dict = dict;
} else {
- void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem);
+ void* dictBuffer;
+ RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
+ "no malloc for static CCtx");
+ dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);
RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!");
- memcpy(dictBuffer, dict, dictSize);
+ ZSTD_memcpy(dictBuffer, dict, dictSize);
cctx->localDict.dictBuffer = dictBuffer;
cctx->localDict.dict = dictBuffer;
}
@@ -938,6 +1171,14 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
return 0;
}
+size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)
+{
+ RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
+ "Can't ref a pool when ctx not in init stage.");
+ cctx->pool = pool;
+ return 0;
+}
+
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
{
return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);
@@ -1022,23 +1263,83 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
return hashLog - btScale;
}
+/** ZSTD_dictAndWindowLog() :
+ * Returns an adjusted window log that is large enough to fit the source and the dictionary.
+ * The zstd format says that the entire dictionary is valid if one byte of the dictionary
+ * is within the window. So the hashLog and chainLog should be large enough to reference both
+ * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing
+ * the hashLog and windowLog.
+ * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN.
+ */
+static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)
+{
+ const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;
+ /* No dictionary ==> No change */
+ if (dictSize == 0) {
+ return windowLog;
+ }
+ assert(windowLog <= ZSTD_WINDOWLOG_MAX);
+ assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */
+ {
+ U64 const windowSize = 1ULL << windowLog;
+ U64 const dictAndWindowSize = dictSize + windowSize;
+ /* If the window size is already large enough to fit both the source and the dictionary
+ * then just use the window size. Otherwise adjust so that it fits the dictionary and
+ * the window.
+ */
+ if (windowSize >= dictSize + srcSize) {
+ return windowLog; /* Window size large enough already */
+ } else if (dictAndWindowSize >= maxWindowSize) {
+ return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */
+ } else {
+ return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;
+ }
+ }
+}
+
/** ZSTD_adjustCParams_internal() :
* optimize `cPar` for a specified input (`srcSize` and `dictSize`).
* mostly downsize to reduce memory consumption and initialization latency.
* `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.
+ * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`.
* note : `srcSize==0` means 0!
* condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */
static ZSTD_compressionParameters
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
unsigned long long srcSize,
- size_t dictSize)
+ size_t dictSize,
+ ZSTD_cParamMode_e mode)
{
- static const U64 minSrcSize = 513; /* (1<<9) + 1 */
- static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
+ const U64 minSrcSize = 513; /* (1<<9) + 1 */
+ const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
assert(ZSTD_checkCParams(cPar)==0);
- if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
- srcSize = minSrcSize;
+ switch (mode) {
+ case ZSTD_cpm_unknown:
+ case ZSTD_cpm_noAttachDict:
+ /* If we don't know the source size, don't make any
+ * assumptions about it. We will already have selected
+ * smaller parameters if a dictionary is in use.
+ */
+ break;
+ case ZSTD_cpm_createCDict:
+ /* Assume a small source size when creating a dictionary
+ * with an unkown source size.
+ */
+ if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
+ srcSize = minSrcSize;
+ break;
+ case ZSTD_cpm_attachDict:
+ /* Dictionary has its own dedicated parameters which have
+ * already been selected. We are selecting parameters
+ * for only the source.
+ */
+ dictSize = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
/* resize windowLog if input is small enough, to use less memory */
if ( (srcSize < maxWindowResize)
@@ -1049,10 +1350,12 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
ZSTD_highbit32(tSize-1) + 1;
if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;
}
- if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1;
- { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
- if (cycleLog > cPar.windowLog)
- cPar.chainLog -= (cycleLog - cPar.windowLog);
+ if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);
+ U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);
+ if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;
+ if (cycleLog > dictAndWindowLog)
+ cPar.chainLog -= (cycleLog - dictAndWindowLog);
}
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
@@ -1068,38 +1371,50 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
{
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
- return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
+ return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown);
}
-static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
-static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize);
+static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
+static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
+
+static void ZSTD_overrideCParams(
+ ZSTD_compressionParameters* cParams,
+ const ZSTD_compressionParameters* overrides)
+{
+ if (overrides->windowLog) cParams->windowLog = overrides->windowLog;
+ if (overrides->hashLog) cParams->hashLog = overrides->hashLog;
+ if (overrides->chainLog) cParams->chainLog = overrides->chainLog;
+ if (overrides->searchLog) cParams->searchLog = overrides->searchLog;
+ if (overrides->minMatch) cParams->minMatch = overrides->minMatch;
+ if (overrides->targetLength) cParams->targetLength = overrides->targetLength;
+ if (overrides->strategy) cParams->strategy = overrides->strategy;
+}
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
- const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize)
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
{
ZSTD_compressionParameters cParams;
if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {
srcSizeHint = CCtxParams->srcSizeHint;
}
- cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize);
+ cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);
if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
- if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog;
- if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog;
- if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog;
- if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog;
- if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch;
- if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength;
- if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy;
+ ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
assert(!ZSTD_checkCParams(cParams));
/* srcSizeHint == 0 means 0 */
- return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize);
+ return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode);
}
static size_t
ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
+ const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const U32 enableDedicatedDictSearch,
const U32 forCCtx)
{
- size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
+ /* chain table size should be 0 for fast or row-hash strategies */
+ size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, enableDedicatedDictSearch && !forCCtx)
+ ? ((size_t)1 << cParams->chainLog)
+ : 0;
size_t const hSize = ((size_t)1) << cParams->hashLog;
U32 const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
@@ -1109,71 +1424,117 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
+ hSize * sizeof(U32)
+ h3Size * sizeof(U32);
size_t const optPotentialSpace =
- ZSTD_cwksp_alloc_size((MaxML+1) * sizeof(U32))
- + ZSTD_cwksp_alloc_size((MaxLL+1) * sizeof(U32))
- + ZSTD_cwksp_alloc_size((MaxOff+1) * sizeof(U32))
- + ZSTD_cwksp_alloc_size((1<<Litbits) * sizeof(U32))
- + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
- + ZSTD_cwksp_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
+ ZSTD_cwksp_aligned_alloc_size((MaxML+1) * sizeof(U32))
+ + ZSTD_cwksp_aligned_alloc_size((MaxLL+1) * sizeof(U32))
+ + ZSTD_cwksp_aligned_alloc_size((MaxOff+1) * sizeof(U32))
+ + ZSTD_cwksp_aligned_alloc_size((1<<Litbits) * sizeof(U32))
+ + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_match_t))
+ + ZSTD_cwksp_aligned_alloc_size((ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
+ size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)
+ ? ZSTD_cwksp_aligned_alloc_size(hSize*sizeof(U16))
+ : 0;
size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))
? optPotentialSpace
: 0;
+ size_t const slackSpace = ZSTD_cwksp_slack_space_required();
+
+ /* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */
+ ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4);
+ assert(useRowMatchFinder != ZSTD_urm_auto);
+
DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
(U32)chainSize, (U32)hSize, (U32)h3Size);
- return tableSpace + optSpace;
+ return tableSpace + optSpace + slackSpace + lazyAdditionalSpace;
+}
+
+static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
+ const ZSTD_compressionParameters* cParams,
+ const ldmParams_t* ldmParams,
+ const int isStatic,
+ const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const size_t buffInSize,
+ const size_t buffOutSize,
+ const U64 pledgedSrcSize)
+{
+ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
+ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
+ U32 const divider = (cParams->minMatch==3) ? 3 : 4;
+ size_t const maxNbSeq = blockSize / divider;
+ size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
+ + ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef))
+ + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
+ size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE);
+ size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
+ size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1);
+
+ size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);
+ size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);
+ size_t const ldmSeqSpace = ldmParams->enableLdm ?
+ ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;
+
+
+ size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)
+ + ZSTD_cwksp_alloc_size(buffOutSize);
+
+ size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
+
+ size_t const neededSpace =
+ cctxSpace +
+ entropySpace +
+ blockStateSpace +
+ ldmSpace +
+ ldmSeqSpace +
+ matchStateSize +
+ tokenSpace +
+ bufferSpace;
+
+ DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
+ return neededSpace;
}
size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
- RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
- { ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
- size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
- U32 const divider = (cParams.minMatch==3) ? 3 : 4;
- size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
- + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
- + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
- size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
- size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
- size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1);
-
- size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams);
- size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq));
+ ZSTD_compressionParameters const cParams =
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
+ ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
+ &cParams);
- /* estimateCCtxSize is for one-shot compression. So no buffers should
- * be needed. However, we still allocate two 0-sized buffers, which can
- * take space under ASAN. */
- size_t const bufferSpace = ZSTD_cwksp_alloc_size(0)
- + ZSTD_cwksp_alloc_size(0);
-
- size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx));
-
- size_t const neededSpace =
- cctxSpace +
- entropySpace +
- blockStateSpace +
- ldmSpace +
- ldmSeqSpace +
- matchStateSize +
- tokenSpace +
- bufferSpace;
-
- DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
- return neededSpace;
- }
+ RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
+ /* estimateCCtxSize is for one-shot compression. So no buffers should
+ * be needed. However, we still allocate two 0-sized buffers, which can
+ * take space under ASAN. */
+ return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
+ &cParams, &params->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN);
}
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
{
- ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
- return ZSTD_estimateCCtxSize_usingCCtxParams(&params);
+ ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);
+ if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {
+ /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */
+ size_t noRowCCtxSize;
+ size_t rowCCtxSize;
+ initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder;
+ noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);
+ initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder;
+ rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);
+ return MAX(noRowCCtxSize, rowCCtxSize);
+ } else {
+ return ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);
+ }
}
static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)
{
- ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
- return ZSTD_estimateCCtxSize_usingCParams(cParams);
+ int tier = 0;
+ size_t largestSize = 0;
+ static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN};
+ for (; tier < 4; ++tier) {
+ /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict);
+ largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize);
+ }
+ return largestSize;
}
size_t ZSTD_estimateCCtxSize(int compressionLevel)
@@ -1181,6 +1542,7 @@ size_t ZSTD_estimateCCtxSize(int compressionLevel)
int level;
size_t memBudget = 0;
for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {
+ /* Ensure monotonically increasing memory usage as compression level increases */
size_t const newMB = ZSTD_estimateCCtxSize_internal(level);
if (newMB > memBudget) memBudget = newMB;
}
@@ -1191,27 +1553,42 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
{ ZSTD_compressionParameters const cParams =
- ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0);
- size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params);
+ ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
- size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
- size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
- size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize)
- + ZSTD_cwksp_alloc_size(outBuffSize);
-
- return CCtxSize + streamingSize;
+ size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
+ ? ((size_t)1 << cParams.windowLog) + blockSize
+ : 0;
+ size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
+ ? ZSTD_compressBound(blockSize) + 1
+ : 0;
+ ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);
+
+ return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
+ &cParams, &params->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
+ ZSTD_CONTENTSIZE_UNKNOWN);
}
}
size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
{
- ZSTD_CCtx_params const params = ZSTD_makeCCtxParamsFromCParams(cParams);
- return ZSTD_estimateCStreamSize_usingCCtxParams(&params);
+ ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);
+ if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {
+ /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */
+ size_t noRowCCtxSize;
+ size_t rowCCtxSize;
+ initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder;
+ noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);
+ initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder;
+ rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);
+ return MAX(noRowCCtxSize, rowCCtxSize);
+ } else {
+ return ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);
+ }
}
static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)
{
- ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
return ZSTD_estimateCStreamSize_usingCParams(cParams);
}
@@ -1305,16 +1682,6 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms)
}
/**
- * Indicates whether this compression proceeds directly from user-provided
- * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
- * whether the context needs to buffer the input/output (ZSTDb_buffered).
- */
-typedef enum {
- ZSTDb_not_buffered,
- ZSTDb_buffered
-} ZSTD_buffered_policy_e;
-
-/**
* Controls, for this matchState reset, whether the tables need to be cleared /
* prepared for the coming compression (ZSTDcrp_makeClean), or whether the
* tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a
@@ -1341,20 +1708,27 @@ typedef enum {
ZSTD_resetTarget_CCtx
} ZSTD_resetTarget_e;
+
static size_t
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
ZSTD_cwksp* ws,
const ZSTD_compressionParameters* cParams,
+ const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
const ZSTD_compResetPolicy_e crp,
const ZSTD_indexResetPolicy_e forceResetIndex,
const ZSTD_resetTarget_e forWho)
{
- size_t const chainSize = (cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cParams->chainLog);
+ /* disable chain table allocation for fast or row-based strategies */
+ size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder,
+ ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict))
+ ? ((size_t)1 << cParams->chainLog)
+ : 0;
size_t const hSize = ((size_t)1) << cParams->hashLog;
U32 const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;
size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
+ assert(useRowMatchFinder != ZSTD_urm_auto);
if (forceResetIndex == ZSTDirp_reset) {
ZSTD_window_init(&ms->window);
ZSTD_cwksp_mark_tables_dirty(ws);
@@ -1393,11 +1767,23 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned(ws, (ZSTD_OPT_NUM+1) * sizeof(ZSTD_optimal_t));
}
+ if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) {
+ { /* Row match finder needs an additional table of hashes ("tags") */
+ size_t const tagTableSize = hSize*sizeof(U16);
+ ms->tagTable = (U16*)ZSTD_cwksp_reserve_aligned(ws, tagTableSize);
+ if (ms->tagTable) ZSTD_memset(ms->tagTable, 0, tagTableSize);
+ }
+ { /* Switch to 32-entry rows if searchLog is 5 (or more) */
+ U32 const rowLog = cParams->searchLog < 5 ? 4 : 5;
+ assert(cParams->hashLog > rowLog);
+ ms->rowHashLog = cParams->hashLog - rowLog;
+ }
+ }
+
ms->cParams = *cParams;
RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,
"failed a workspace allocation in ZSTD_reset_matchState");
-
return 0;
}
@@ -1414,75 +1800,85 @@ static int ZSTD_indexTooCloseToMax(ZSTD_window_t w)
return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);
}
+/** ZSTD_dictTooBig():
+ * When dictionaries are larger than ZSTD_CHUNKSIZE_MAX they can't be loaded in
+ * one go generically. So we ensure that in that case we reset the tables to zero,
+ * so that we can load as much of the dictionary as possible.
+ */
+static int ZSTD_dictTooBig(size_t const loadedDictSize)
+{
+ return loadedDictSize > ZSTD_CHUNKSIZE_MAX;
+}
+
/*! ZSTD_resetCCtx_internal() :
- note : `params` are assumed fully validated at this stage */
+ * @param loadedDictSize The size of the dictionary to be loaded
+ * into the context, if any. If no dictionary is used, or the
+ * dictionary is being attached / copied, then pass 0.
+ * note : `params` are assumed fully validated at this stage.
+ */
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
- ZSTD_CCtx_params params,
+ ZSTD_CCtx_params const* params,
U64 const pledgedSrcSize,
+ size_t const loadedDictSize,
ZSTD_compResetPolicy_e const crp,
ZSTD_buffered_policy_e const zbuff)
{
ZSTD_cwksp* const ws = &zc->workspace;
- DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u",
- (U32)pledgedSrcSize, params.cParams.windowLog);
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
+ DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d",
+ (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder);
+ assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
zc->isFirstBlock = 1;
- if (params.ldmParams.enableLdm) {
+ /* Set applied params early so we can modify them for LDM,
+ * and point params at the applied params.
+ */
+ zc->appliedParams = *params;
+ params = &zc->appliedParams;
+
+ assert(params->useRowMatchFinder != ZSTD_urm_auto);
+ if (params->ldmParams.enableLdm) {
/* Adjust long distance matching parameters */
- ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
- assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
- assert(params.ldmParams.hashRateLog < 32);
- zc->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
+ ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, &params->cParams);
+ assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog);
+ assert(params->ldmParams.hashRateLog < 32);
}
- { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params.cParams.windowLog), pledgedSrcSize));
+ { size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
- U32 const divider = (params.cParams.minMatch==3) ? 3 : 4;
+ U32 const divider = (params->cParams.minMatch==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
- size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
- + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef))
- + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
- size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
- size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0;
- size_t const matchStateSize = ZSTD_sizeof_matchState(&params.cParams, /* forCCtx */ 1);
- size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize);
-
- ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset;
-
- if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) {
- needsIndexReset = ZSTDirp_reset;
- }
+ size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)
+ ? ZSTD_compressBound(blockSize) + 1
+ : 0;
+ size_t const buffInSize = (zbuff == ZSTDb_buffered && params->inBufferMode == ZSTD_bm_buffered)
+ ? windowSize + blockSize
+ : 0;
+ size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize);
+
+ int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);
+ int const dictTooBig = ZSTD_dictTooBig(loadedDictSize);
+ ZSTD_indexResetPolicy_e needsIndexReset =
+ (indexTooClose || dictTooBig || !zc->initialized) ? ZSTDirp_reset : ZSTDirp_continue;
- if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
+ size_t const neededSpace =
+ ZSTD_estimateCCtxSize_usingCCtxParams_internal(
+ &params->cParams, &params->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,
+ buffInSize, buffOutSize, pledgedSrcSize);
+ int resizeWorkspace;
- /* Check if workspace is large enough, alloc a new one if needed */
- { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
- size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE);
- size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));
- size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize);
- size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams);
- size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq));
-
- size_t const neededSpace =
- cctxSpace +
- entropySpace +
- blockStateSpace +
- ldmSpace +
- ldmSeqSpace +
- matchStateSize +
- tokenSpace +
- bufferSpace;
+ FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
+
+ if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);
+ { /* Check if workspace is large enough, alloc a new one if needed */
int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;
int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);
-
- DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers",
- neededSpace>>10, matchStateSize>>10, bufferSpace>>10);
+ resizeWorkspace = workspaceTooSmall || workspaceWasteful;
+ DEBUGLOG(4, "Need %zu B workspace", neededSpace);
DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize);
- if (workspaceTooSmall || workspaceWasteful) {
+ if (resizeWorkspace) {
DEBUGLOG(4, "Resize workspaceSize from %zuKB to %zuKB",
ZSTD_cwksp_sizeof(ws) >> 10,
neededSpace >> 10);
@@ -1503,15 +1899,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock");
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
- zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE);
+ zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
} }
ZSTD_cwksp_clear(ws);
/* init params */
- zc->appliedParams = params;
- zc->blockState.matchState.cParams = params.cParams;
+ zc->blockState.matchState.cParams = params->cParams;
zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
zc->consumedSrcSize = 0;
zc->producedCSize = 0;
@@ -1524,6 +1919,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
XXH64_reset(&zc->xxhState, 0);
zc->stage = ZSTDcs_init;
zc->dictID = 0;
+ zc->dictContentSize = 0;
ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);
@@ -1534,19 +1930,20 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->seqStore.maxNbLit = blockSize;
/* buffers */
+ zc->bufferedPolicy = zbuff;
zc->inBuffSize = buffInSize;
zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);
zc->outBuffSize = buffOutSize;
zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
/* ldm bucketOffsets table */
- if (params.ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm) {
/* TODO: avoid memset? */
- size_t const ldmBucketSize =
- ((size_t)1) << (params.ldmParams.hashLog -
- params.ldmParams.bucketSizeLog);
- zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize);
- memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize);
+ size_t const numBuckets =
+ ((size_t)1) << (params->ldmParams.hashLog -
+ params->ldmParams.bucketSizeLog);
+ zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);
+ ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);
}
/* sequences storage */
@@ -1560,26 +1957,28 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
FORWARD_IF_ERROR(ZSTD_reset_matchState(
&zc->blockState.matchState,
ws,
- &params.cParams,
+ &params->cParams,
+ params->useRowMatchFinder,
crp,
needsIndexReset,
ZSTD_resetTarget_CCtx), "");
/* ldm hash table */
- if (params.ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm) {
/* TODO: avoid memset? */
- size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog;
+ size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog;
zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
- memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
+ ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));
zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq));
zc->maxNbLdmSequences = maxNbLdmSeq;
ZSTD_window_init(&zc->ldmState.window);
- ZSTD_window_clear(&zc->ldmState.window);
zc->ldmState.loadedDictEnd = 0;
}
+ assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace, resizeWorkspace));
DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
+
zc->initialized = 1;
return 0;
@@ -1618,12 +2017,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,
U64 pledgedSrcSize)
{
size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];
- return ( pledgedSrcSize <= cutoff
- || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
- || params->attachDictPref == ZSTD_dictForceAttach )
- && params->attachDictPref != ZSTD_dictForceCopy
- && !params->forceWindow; /* dictMatchState isn't correctly
- * handled in _enforceMaxDist */
+ int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;
+ return dedicatedDictSearch
+ || ( ( pledgedSrcSize <= cutoff
+ || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
+ || params->attachDictPref == ZSTD_dictForceAttach )
+ && params->attachDictPref != ZSTD_dictForceCopy
+ && !params->forceWindow ); /* dictMatchState isn't correctly
+ * handled in _enforceMaxDist */
}
static size_t
@@ -1633,17 +2034,28 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
{
- { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams;
+ DEBUGLOG(4, "ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu",
+ (unsigned long long)pledgedSrcSize);
+ {
+ ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;
unsigned const windowLog = params.cParams.windowLog;
assert(windowLog != 0);
/* Resize working context table params for input only, since the dict
* has its own tables. */
- /* pledgeSrcSize == 0 means 0! */
- params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0);
+ /* pledgedSrcSize == 0 means 0! */
+
+ if (cdict->matchState.dedicatedDictSearch) {
+ ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);
+ }
+
+ params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,
+ cdict->dictContentSize, ZSTD_cpm_attachDict);
params.cParams.windowLog = windowLog;
- FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,
+ /* loadedDictSize */ 0,
ZSTDcrp_makeClean, zbuff), "");
- assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
+ assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);
}
{ const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc
@@ -1668,9 +2080,10 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
} }
cctx->dictID = cdict->dictID;
+ cctx->dictContentSize = cdict->dictContentSize;
/* copy block state */
- memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
+ ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
return 0;
}
@@ -1683,14 +2096,18 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
{
const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;
- DEBUGLOG(4, "copying dictionary into context");
+ assert(!cdict->matchState.dedicatedDictSearch);
+ DEBUGLOG(4, "ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu",
+ (unsigned long long)pledgedSrcSize);
{ unsigned const windowLog = params.cParams.windowLog;
assert(windowLog != 0);
/* Copy only compression parameters related to tables. */
params.cParams = *cdict_cParams;
params.cParams.windowLog = windowLog;
- FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ params.useRowMatchFinder = cdict->useRowMatchFinder;
+ FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,
+ /* loadedDictSize */ 0,
ZSTDcrp_leaveDirty, zbuff), "");
assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);
assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);
@@ -1698,24 +2115,37 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
}
ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
+ assert(params.useRowMatchFinder != ZSTD_urm_auto);
/* copy tables */
- { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog);
+ { size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */)
+ ? ((size_t)1 << cdict_cParams->chainLog)
+ : 0;
size_t const hSize = (size_t)1 << cdict_cParams->hashLog;
- memcpy(cctx->blockState.matchState.hashTable,
+ ZSTD_memcpy(cctx->blockState.matchState.hashTable,
cdict->matchState.hashTable,
hSize * sizeof(U32));
- memcpy(cctx->blockState.matchState.chainTable,
+ /* Do not copy cdict's chainTable if cctx has parameters such that it would not use chainTable */
+ if (ZSTD_allocateChainTable(cctx->appliedParams.cParams.strategy, cctx->appliedParams.useRowMatchFinder, 0 /* forDDSDict */)) {
+ ZSTD_memcpy(cctx->blockState.matchState.chainTable,
cdict->matchState.chainTable,
chainSize * sizeof(U32));
+ }
+ /* copy tag table */
+ if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) {
+ size_t const tagTableSize = hSize*sizeof(U16);
+ ZSTD_memcpy(cctx->blockState.matchState.tagTable,
+ cdict->matchState.tagTable,
+ tagTableSize);
+ }
}
/* Zero the hashTable3, since the cdict never fills it */
{ int const h3log = cctx->blockState.matchState.hashLog3;
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
assert(cdict->matchState.hashLog3 == 0);
- memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
+ ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));
}
ZSTD_cwksp_mark_tables_clean(&cctx->workspace);
@@ -1729,9 +2159,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
}
cctx->dictID = cdict->dictID;
+ cctx->dictContentSize = cdict->dictContentSize;
/* copy block state */
- memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
+ ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));
return 0;
}
@@ -1771,16 +2202,18 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
{
- DEBUGLOG(5, "ZSTD_copyCCtx_internal");
RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,
"Can't copy a ctx that's not in init stage.");
-
- memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
+ DEBUGLOG(5, "ZSTD_copyCCtx_internal");
+ ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
/* Copy only compression parameters related to tables. */
params.cParams = srcCCtx->appliedParams.cParams;
+ assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_urm_auto);
+ params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder;
params.fParams = fParams;
- ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
+ ZSTD_resetCCtx_internal(dstCCtx, &params, pledgedSrcSize,
+ /* loadedDictSize */ 0,
ZSTDcrp_leaveDirty, zbuff);
assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);
assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);
@@ -1792,18 +2225,22 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);
/* copy tables */
- { size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog);
+ { size_t const chainSize = ZSTD_allocateChainTable(srcCCtx->appliedParams.cParams.strategy,
+ srcCCtx->appliedParams.useRowMatchFinder,
+ 0 /* forDDSDict */)
+ ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog)
+ : 0;
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
int const h3log = srcCCtx->blockState.matchState.hashLog3;
size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;
- memcpy(dstCCtx->blockState.matchState.hashTable,
+ ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,
srcCCtx->blockState.matchState.hashTable,
hSize * sizeof(U32));
- memcpy(dstCCtx->blockState.matchState.chainTable,
+ ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,
srcCCtx->blockState.matchState.chainTable,
chainSize * sizeof(U32));
- memcpy(dstCCtx->blockState.matchState.hashTable3,
+ ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,
srcCCtx->blockState.matchState.hashTable3,
h3Size * sizeof(U32));
}
@@ -1819,9 +2256,10 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;
}
dstCCtx->dictID = srcCCtx->dictID;
+ dstCCtx->dictContentSize = srcCCtx->dictContentSize;
/* copy block state */
- memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
+ ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));
return 0;
}
@@ -1834,7 +2272,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
{
ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
- ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0);
+ ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;
ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);
@@ -1861,7 +2299,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
assert(size < (1U<<31)); /* can be casted to int */
-#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
+#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
/* To validate that the table re-use logic is sound, and that we don't
* access table space that we haven't cleaned, we re-"poison" the table
* space every time we mark it dirty.
@@ -1905,7 +2343,7 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par
ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);
}
- if (params->cParams.strategy != ZSTD_fast) {
+ if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) {
U32 const chainSize = (U32)1 << params->cParams.chainLog;
if (params->cParams.strategy == ZSTD_btlazy2)
ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);
@@ -1942,9 +2380,9 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
}
- if (seqStorePtr->longLengthID==1)
+ if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)
llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
- if (seqStorePtr->longLengthID==2)
+ if (seqStorePtr->longLengthType==ZSTD_llt_matchLength)
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
}
@@ -1958,10 +2396,158 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
return (cctxParams->targetCBlockSize != 0);
}
-/* ZSTD_compressSequences_internal():
- * actually compresses both literals and sequences */
+/* ZSTD_blockSplitterEnabled():
+ * Returns if block splitting param is being used
+ * If used, compression will do best effort to split a block in order to improve compression ratio.
+ * Returns 1 if true, 0 otherwise. */
+static int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams)
+{
+ DEBUGLOG(5, "ZSTD_blockSplitterEnabled(splitBlocks=%d)", cctxParams->splitBlocks);
+ return (cctxParams->splitBlocks != 0);
+}
+
+/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types
+ * and size of the sequences statistics
+ */
+typedef struct {
+ U32 LLtype;
+ U32 Offtype;
+ U32 MLtype;
+ size_t size;
+ size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
+} ZSTD_symbolEncodingTypeStats_t;
+
+/* ZSTD_buildSequencesStatistics():
+ * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field.
+ * Modifies `nextEntropy` to have the appropriate values as a side effect.
+ * nbSeq must be greater than 0.
+ *
+ * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32)
+ */
+static ZSTD_symbolEncodingTypeStats_t
+ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
+ const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,
+ BYTE* dst, const BYTE* const dstEnd,
+ ZSTD_strategy strategy, unsigned* countWorkspace,
+ void* entropyWorkspace, size_t entropyWkspSize) {
+ BYTE* const ostart = dst;
+ const BYTE* const oend = dstEnd;
+ BYTE* op = ostart;
+ FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
+ FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
+ FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
+ const BYTE* const ofCodeTable = seqStorePtr->ofCode;
+ const BYTE* const llCodeTable = seqStorePtr->llCode;
+ const BYTE* const mlCodeTable = seqStorePtr->mlCode;
+ ZSTD_symbolEncodingTypeStats_t stats;
+
+ stats.lastCountSize = 0;
+ /* convert length/distances into codes */
+ ZSTD_seqToCodes(seqStorePtr);
+ assert(op <= oend);
+ assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */
+ /* build CTable for Literal Lengths */
+ { unsigned max = MaxLL;
+ size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
+ DEBUGLOG(5, "Building LL table");
+ nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
+ stats.LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
+ countWorkspace, max, mostFrequent, nbSeq,
+ LLFSELog, prevEntropy->litlengthCTable,
+ LL_defaultNorm, LL_defaultNormLog,
+ ZSTD_defaultAllowed, strategy);
+ assert(set_basic < set_compressed && set_rle < set_compressed);
+ assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+ { size_t const countSize = ZSTD_buildCTable(
+ op, (size_t)(oend - op),
+ CTable_LitLength, LLFSELog, (symbolEncodingType_e)stats.LLtype,
+ countWorkspace, max, llCodeTable, nbSeq,
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
+ prevEntropy->litlengthCTable,
+ sizeof(prevEntropy->litlengthCTable),
+ entropyWorkspace, entropyWkspSize);
+ if (ZSTD_isError(countSize)) {
+ DEBUGLOG(3, "ZSTD_buildCTable for LitLens failed");
+ stats.size = countSize;
+ return stats;
+ }
+ if (stats.LLtype == set_compressed)
+ stats.lastCountSize = countSize;
+ op += countSize;
+ assert(op <= oend);
+ } }
+ /* build CTable for Offsets */
+ { unsigned max = MaxOff;
+ size_t const mostFrequent = HIST_countFast_wksp(
+ countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
+ /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
+ ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
+ DEBUGLOG(5, "Building OF table");
+ nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
+ stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
+ countWorkspace, max, mostFrequent, nbSeq,
+ OffFSELog, prevEntropy->offcodeCTable,
+ OF_defaultNorm, OF_defaultNormLog,
+ defaultPolicy, strategy);
+ assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+ { size_t const countSize = ZSTD_buildCTable(
+ op, (size_t)(oend - op),
+ CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)stats.Offtype,
+ countWorkspace, max, ofCodeTable, nbSeq,
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
+ prevEntropy->offcodeCTable,
+ sizeof(prevEntropy->offcodeCTable),
+ entropyWorkspace, entropyWkspSize);
+ if (ZSTD_isError(countSize)) {
+ DEBUGLOG(3, "ZSTD_buildCTable for Offsets failed");
+ stats.size = countSize;
+ return stats;
+ }
+ if (stats.Offtype == set_compressed)
+ stats.lastCountSize = countSize;
+ op += countSize;
+ assert(op <= oend);
+ } }
+ /* build CTable for MatchLengths */
+ { unsigned max = MaxML;
+ size_t const mostFrequent = HIST_countFast_wksp(
+ countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
+ DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
+ nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
+ stats.MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
+ countWorkspace, max, mostFrequent, nbSeq,
+ MLFSELog, prevEntropy->matchlengthCTable,
+ ML_defaultNorm, ML_defaultNormLog,
+ ZSTD_defaultAllowed, strategy);
+ assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
+ { size_t const countSize = ZSTD_buildCTable(
+ op, (size_t)(oend - op),
+ CTable_MatchLength, MLFSELog, (symbolEncodingType_e)stats.MLtype,
+ countWorkspace, max, mlCodeTable, nbSeq,
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
+ prevEntropy->matchlengthCTable,
+ sizeof(prevEntropy->matchlengthCTable),
+ entropyWorkspace, entropyWkspSize);
+ if (ZSTD_isError(countSize)) {
+ DEBUGLOG(3, "ZSTD_buildCTable for MatchLengths failed");
+ stats.size = countSize;
+ return stats;
+ }
+ if (stats.MLtype == set_compressed)
+ stats.lastCountSize = countSize;
+ op += countSize;
+ assert(op <= oend);
+ } }
+ stats.size = (size_t)(op-ostart);
+ return stats;
+}
+
+/* ZSTD_entropyCompressSeqStore_internal():
+ * compresses both literals and sequences
+ * Returns compressed size of block, or a zstd error.
+ */
MEM_STATIC size_t
-ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
+ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
const ZSTD_entropyCTables_t* prevEntropy,
ZSTD_entropyCTables_t* nextEntropy,
const ZSTD_CCtx_params* cctxParams,
@@ -1971,24 +2557,26 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
{
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
ZSTD_strategy const strategy = cctxParams->cParams.strategy;
- unsigned count[MaxSeq+1];
+ unsigned* count = (unsigned*)entropyWorkspace;
FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
- U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
const seqDef* const sequences = seqStorePtr->sequencesStart;
+ const size_t nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
const BYTE* const llCodeTable = seqStorePtr->llCode;
const BYTE* const mlCodeTable = seqStorePtr->mlCode;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstCapacity;
BYTE* op = ostart;
- size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
- BYTE* seqHead;
- BYTE* lastNCount = NULL;
+ size_t lastCountSize;
+
+ entropyWorkspace = count + (MaxSeq + 1);
+ entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
- DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq);
+ DEBUGLOG(4, "ZSTD_entropyCompressSeqStore_internal (nbSeq=%zu)", nbSeq);
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
+ assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);
/* Compress literals */
{ const BYTE* const literals = seqStorePtr->litStart;
@@ -2023,98 +2611,23 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
assert(op <= oend);
if (nbSeq==0) {
/* Copy the old tables over as if we repeated them */
- memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
+ ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));
return (size_t)(op - ostart);
}
-
- /* seqHead : flags for FSE encoding type */
- seqHead = op++;
- assert(op <= oend);
-
- /* convert length/distances into codes */
- ZSTD_seqToCodes(seqStorePtr);
- /* build CTable for Literal Lengths */
- { unsigned max = MaxLL;
- size_t const mostFrequent = HIST_countFast_wksp(count, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
- DEBUGLOG(5, "Building LL table");
- nextEntropy->fse.litlength_repeatMode = prevEntropy->fse.litlength_repeatMode;
- LLtype = ZSTD_selectEncodingType(&nextEntropy->fse.litlength_repeatMode,
- count, max, mostFrequent, nbSeq,
- LLFSELog, prevEntropy->fse.litlengthCTable,
- LL_defaultNorm, LL_defaultNormLog,
- ZSTD_defaultAllowed, strategy);
- assert(set_basic < set_compressed && set_rle < set_compressed);
- assert(!(LLtype < set_compressed && nextEntropy->fse.litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(
- op, (size_t)(oend - op),
- CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
- count, max, llCodeTable, nbSeq,
- LL_defaultNorm, LL_defaultNormLog, MaxLL,
- prevEntropy->fse.litlengthCTable,
- sizeof(prevEntropy->fse.litlengthCTable),
- entropyWorkspace, entropyWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
- if (LLtype == set_compressed)
- lastNCount = op;
- op += countSize;
- assert(op <= oend);
- } }
- /* build CTable for Offsets */
- { unsigned max = MaxOff;
- size_t const mostFrequent = HIST_countFast_wksp(
- count, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
- /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
- ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
- DEBUGLOG(5, "Building OF table");
- nextEntropy->fse.offcode_repeatMode = prevEntropy->fse.offcode_repeatMode;
- Offtype = ZSTD_selectEncodingType(&nextEntropy->fse.offcode_repeatMode,
- count, max, mostFrequent, nbSeq,
- OffFSELog, prevEntropy->fse.offcodeCTable,
- OF_defaultNorm, OF_defaultNormLog,
- defaultPolicy, strategy);
- assert(!(Offtype < set_compressed && nextEntropy->fse.offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(
- op, (size_t)(oend - op),
- CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
- count, max, ofCodeTable, nbSeq,
- OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
- prevEntropy->fse.offcodeCTable,
- sizeof(prevEntropy->fse.offcodeCTable),
- entropyWorkspace, entropyWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
- if (Offtype == set_compressed)
- lastNCount = op;
- op += countSize;
- assert(op <= oend);
- } }
- /* build CTable for MatchLengths */
- { unsigned max = MaxML;
- size_t const mostFrequent = HIST_countFast_wksp(
- count, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize); /* can't fail */
- DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
- nextEntropy->fse.matchlength_repeatMode = prevEntropy->fse.matchlength_repeatMode;
- MLtype = ZSTD_selectEncodingType(&nextEntropy->fse.matchlength_repeatMode,
- count, max, mostFrequent, nbSeq,
- MLFSELog, prevEntropy->fse.matchlengthCTable,
- ML_defaultNorm, ML_defaultNormLog,
- ZSTD_defaultAllowed, strategy);
- assert(!(MLtype < set_compressed && nextEntropy->fse.matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(
- op, (size_t)(oend - op),
- CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
- count, max, mlCodeTable, nbSeq,
- ML_defaultNorm, ML_defaultNormLog, MaxML,
- prevEntropy->fse.matchlengthCTable,
- sizeof(prevEntropy->fse.matchlengthCTable),
- entropyWorkspace, entropyWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
- if (MLtype == set_compressed)
- lastNCount = op;
- op += countSize;
- assert(op <= oend);
- } }
-
- *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
+ {
+ ZSTD_symbolEncodingTypeStats_t stats;
+ BYTE* seqHead = op++;
+ /* build stats for sequences */
+ stats = ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
+ &prevEntropy->fse, &nextEntropy->fse,
+ op, oend,
+ strategy, count,
+ entropyWorkspace, entropyWkspSize);
+ FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!");
+ *seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2));
+ lastCountSize = stats.lastCountSize;
+ op += stats.size;
+ }
{ size_t const bitstreamSize = ZSTD_encodeSequences(
op, (size_t)(oend - op),
@@ -2134,9 +2647,9 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
* In this exceedingly rare case, we will simply emit an uncompressed
* block, since it isn't worth optimizing.
*/
- if (lastNCount && (op - lastNCount) < 4) {
- /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
- assert(op - lastNCount == 3);
+ if (lastCountSize && (lastCountSize + bitstreamSize) < 4) {
+ /* lastCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */
+ assert(lastCountSize + bitstreamSize == 3);
DEBUGLOG(5, "Avoiding bug in zstd decoder in versions <= 1.3.4 by "
"emitting an uncompressed block.");
return 0;
@@ -2148,7 +2661,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr,
}
MEM_STATIC size_t
-ZSTD_compressSequences(seqStore_t* seqStorePtr,
+ZSTD_entropyCompressSeqStore(seqStore_t* seqStorePtr,
const ZSTD_entropyCTables_t* prevEntropy,
ZSTD_entropyCTables_t* nextEntropy,
const ZSTD_CCtx_params* cctxParams,
@@ -2157,7 +2670,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
void* entropyWorkspace, size_t entropyWkspSize,
int bmi2)
{
- size_t const cSize = ZSTD_compressSequences_internal(
+ size_t const cSize = ZSTD_entropyCompressSeqStore_internal(
seqStorePtr, prevEntropy, nextEntropy, cctxParams,
dst, dstCapacity,
entropyWorkspace, entropyWkspSize, bmi2);
@@ -2167,22 +2680,22 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr,
*/
if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity))
return 0; /* block not compressed */
- FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed");
+ FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSeqStore_internal failed");
/* Check compressibility */
{ size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy);
if (cSize >= maxCSize) return 0; /* block not compressed */
}
-
+ DEBUGLOG(4, "ZSTD_entropyCompressSeqStore() cSize: %zu", cSize);
return cSize;
}
/* ZSTD_selectBlockCompressor() :
* Not static, but internal use only (used by long distance matcher)
* assumption : strat is a valid strategy */
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode)
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e useRowMatchFinder, ZSTD_dictMode_e dictMode)
{
- static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = {
+ static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
{ ZSTD_compressBlock_fast /* default for 0 */,
ZSTD_compressBlock_fast,
ZSTD_compressBlock_doubleFast,
@@ -2212,13 +2725,44 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo
ZSTD_compressBlock_btlazy2_dictMatchState,
ZSTD_compressBlock_btopt_dictMatchState,
ZSTD_compressBlock_btultra_dictMatchState,
- ZSTD_compressBlock_btultra_dictMatchState }
+ ZSTD_compressBlock_btultra_dictMatchState },
+ { NULL /* default for 0 */,
+ NULL,
+ NULL,
+ ZSTD_compressBlock_greedy_dedicatedDictSearch,
+ ZSTD_compressBlock_lazy_dedicatedDictSearch,
+ ZSTD_compressBlock_lazy2_dedicatedDictSearch,
+ NULL,
+ NULL,
+ NULL,
+ NULL }
};
ZSTD_blockCompressor selectedCompressor;
ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
- selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
+ DEBUGLOG(4, "Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d", (int)dictMode, (int)strat, (int)useRowMatchFinder);
+ if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) {
+ static const ZSTD_blockCompressor rowBasedBlockCompressors[4][3] = {
+ { ZSTD_compressBlock_greedy_row,
+ ZSTD_compressBlock_lazy_row,
+ ZSTD_compressBlock_lazy2_row },
+ { ZSTD_compressBlock_greedy_extDict_row,
+ ZSTD_compressBlock_lazy_extDict_row,
+ ZSTD_compressBlock_lazy2_extDict_row },
+ { ZSTD_compressBlock_greedy_dictMatchState_row,
+ ZSTD_compressBlock_lazy_dictMatchState_row,
+ ZSTD_compressBlock_lazy2_dictMatchState_row },
+ { ZSTD_compressBlock_greedy_dedicatedDictSearch_row,
+ ZSTD_compressBlock_lazy_dedicatedDictSearch_row,
+ ZSTD_compressBlock_lazy2_dedicatedDictSearch_row }
+ };
+ DEBUGLOG(4, "Selecting a row-based matchfinder");
+ assert(useRowMatchFinder != ZSTD_urm_auto);
+ selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy];
+ } else {
+ selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
+ }
assert(selectedCompressor != NULL);
return selectedCompressor;
}
@@ -2226,7 +2770,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo
static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr,
const BYTE* anchor, size_t lastLLSize)
{
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
+ ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);
seqStorePtr->lit += lastLLSize;
}
@@ -2234,7 +2778,7 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
{
ssPtr->lit = ssPtr->litStart;
ssPtr->sequences = ssPtr->sequencesStart;
- ssPtr->longLengthID = 0;
+ ssPtr->longLengthType = ZSTD_llt_none;
}
typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
@@ -2247,7 +2791,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
/* Assert that we have correctly flushed the ctx params into the ms's copy */
ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
- ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
+ if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {
+ ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);
+ } else {
+ ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);
+ }
return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */
}
ZSTD_resetSeqStore(&(zc->seqStore));
@@ -2263,10 +2811,10 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
/* limited update after a very long match */
{ const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
- const U32 current = (U32)(istart-base);
+ const U32 curr = (U32)(istart-base);
if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */
- if (current > ms->nextToUpdate + 384)
- ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384));
+ if (curr > ms->nextToUpdate + 384)
+ ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));
}
/* select and store sequences */
@@ -2283,10 +2831,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
ZSTD_ldm_blockCompress(&zc->externSeqStore,
ms, &zc->seqStore,
zc->blockState.nextCBlock->rep,
+ zc->appliedParams.useRowMatchFinder,
src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
} else if (zc->appliedParams.ldmParams.enableLdm) {
- rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0};
+ rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
ldmSeqStore.seq = zc->ldmSequences;
ldmSeqStore.capacity = zc->maxNbLdmSequences;
@@ -2299,10 +2848,14 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
ZSTD_ldm_blockCompress(&ldmSeqStore,
ms, &zc->seqStore,
zc->blockState.nextCBlock->rep,
+ zc->appliedParams.useRowMatchFinder,
src, srcSize);
assert(ldmSeqStore.pos == ldmSeqStore.size);
} else { /* not long range mode */
- ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode);
+ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy,
+ zc->appliedParams.useRowMatchFinder,
+ dictMode);
+ ms->ldmSeqStore = NULL;
lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
}
{ const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;
@@ -2314,59 +2867,72 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
{
const seqStore_t* seqStore = ZSTD_getSeqStore(zc);
- const seqDef* seqs = seqStore->sequencesStart;
- size_t seqsSize = seqStore->sequences - seqs;
+ const seqDef* seqStoreSeqs = seqStore->sequencesStart;
+ size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs;
+ size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart);
+ size_t literalsRead = 0;
+ size_t lastLLSize;
ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex];
- size_t i; size_t position; int repIdx;
+ size_t i;
+ repcodes_t updatedRepcodes;
assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences);
- for (i = 0, position = 0; i < seqsSize; ++i) {
- outSeqs[i].offset = seqs[i].offset;
- outSeqs[i].litLength = seqs[i].litLength;
- outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH;
+ /* Ensure we have enough space for last literals "sequence" */
+ assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
+ ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
+ for (i = 0; i < seqStoreSeqSize; ++i) {
+ U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM;
+ outSeqs[i].litLength = seqStoreSeqs[i].litLength;
+ outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
+ outSeqs[i].rep = 0;
if (i == seqStore->longLengthPos) {
- if (seqStore->longLengthID == 1) {
+ if (seqStore->longLengthType == ZSTD_llt_literalLength) {
outSeqs[i].litLength += 0x10000;
- } else if (seqStore->longLengthID == 2) {
+ } else if (seqStore->longLengthType == ZSTD_llt_matchLength) {
outSeqs[i].matchLength += 0x10000;
}
}
- if (outSeqs[i].offset <= ZSTD_REP_NUM) {
- outSeqs[i].rep = outSeqs[i].offset;
- repIdx = (unsigned int)i - outSeqs[i].offset;
-
- if (outSeqs[i].litLength == 0) {
- if (outSeqs[i].offset < 3) {
- --repIdx;
+ if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
+ /* Derive the correct offset corresponding to a repcode */
+ outSeqs[i].rep = seqStoreSeqs[i].offset;
+ if (outSeqs[i].litLength != 0) {
+ rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
+ } else {
+ if (outSeqs[i].rep == 3) {
+ rawOffset = updatedRepcodes.rep[0] - 1;
} else {
- repIdx = (unsigned int)i - 1;
+ rawOffset = updatedRepcodes.rep[outSeqs[i].rep];
}
- ++outSeqs[i].rep;
- }
- assert(repIdx >= -3);
- outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1];
- if (outSeqs[i].rep == 4) {
- --outSeqs[i].offset;
}
- } else {
- outSeqs[i].offset -= ZSTD_REP_NUM;
}
-
- position += outSeqs[i].litLength;
- outSeqs[i].matchPos = (unsigned int)position;
- position += outSeqs[i].matchLength;
+ outSeqs[i].offset = rawOffset;
+ /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
+ so we provide seqStoreSeqs[i].offset - 1 */
+ updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
+ seqStoreSeqs[i].offset - 1,
+ seqStoreSeqs[i].litLength == 0);
+ literalsRead += outSeqs[i].litLength;
}
- zc->seqCollector.seqIndex += seqsSize;
+ /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
+ * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker
+ * for the block boundary, according to the API.
+ */
+ assert(seqStoreLiteralsSize >= literalsRead);
+ lastLLSize = seqStoreLiteralsSize - literalsRead;
+ outSeqs[i].litLength = (U32)lastLLSize;
+ outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0;
+ seqStoreSeqSize++;
+ zc->seqCollector.seqIndex += seqStoreSeqSize;
}
-size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
- size_t outSeqsSize, const void* src, size_t srcSize)
+size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
+ size_t outSeqsSize, const void* src, size_t srcSize)
{
const size_t dstCapacity = ZSTD_compressBound(srcSize);
- void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem);
+ void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);
SeqCollector seqCollector;
RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!");
@@ -2378,16 +2944,47 @@ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
zc->seqCollector = seqCollector;
ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);
- ZSTD_free(dst, ZSTD_defaultCMem);
+ ZSTD_customFree(dst, ZSTD_defaultCMem);
return zc->seqCollector.seqIndex;
}
-/* Returns true if the given block is a RLE block */
-static int ZSTD_isRLE(const BYTE *ip, size_t length) {
+size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {
+ size_t in = 0;
+ size_t out = 0;
+ for (; in < seqsSize; ++in) {
+ if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {
+ if (in != seqsSize - 1) {
+ sequences[in+1].litLength += sequences[in].litLength;
+ }
+ } else {
+ sequences[out] = sequences[in];
+ ++out;
+ }
+ }
+ return out;
+}
+
+/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */
+static int ZSTD_isRLE(const BYTE* src, size_t length) {
+ const BYTE* ip = src;
+ const BYTE value = ip[0];
+ const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);
+ const size_t unrollSize = sizeof(size_t) * 4;
+ const size_t unrollMask = unrollSize - 1;
+ const size_t prefixLength = length & unrollMask;
size_t i;
- if (length < 2) return 1;
- for (i = 1; i < length; ++i) {
- if (ip[0] != ip[i]) return 0;
+ size_t u;
+ if (length == 1) return 1;
+ /* Check if prefix is RLE first before using unrolled loop */
+ if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {
+ return 0;
+ }
+ for (i = prefixLength; i != length; i += unrollSize) {
+ for (u = 0; u < unrollSize; u += sizeof(size_t)) {
+ if (MEM_readST(ip + i + u) != valueST) {
+ return 0;
+ }
+ }
}
return 1;
}
@@ -2404,11 +3001,713 @@ static int ZSTD_maybeRLE(seqStore_t const* seqStore)
return nbSeqs < 4 && nbLits < 10;
}
-static void ZSTD_confirmRepcodesAndEntropyTables(ZSTD_CCtx* zc)
+static void ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)
+{
+ ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock;
+ bs->prevCBlock = bs->nextCBlock;
+ bs->nextCBlock = tmp;
+}
+
+/* Writes the block header */
+static void writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock) {
+ U32 const cBlockHeader = cSize == 1 ?
+ lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
+ lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
+ MEM_writeLE24(op, cBlockHeader);
+ DEBUGLOG(3, "writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u", cSize, blockSize, lastBlock);
+}
+
+/** ZSTD_buildBlockEntropyStats_literals() :
+ * Builds entropy for the literals.
+ * Stores literals block type (raw, rle, compressed, repeat) and
+ * huffman description table to hufMetadata.
+ * Requires ENTROPY_WORKSPACE_SIZE workspace
+ * @return : size of huffman description table or error code */
+static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize,
+ const ZSTD_hufCTables_t* prevHuf,
+ ZSTD_hufCTables_t* nextHuf,
+ ZSTD_hufCTablesMetadata_t* hufMetadata,
+ const int disableLiteralsCompression,
+ void* workspace, size_t wkspSize)
+{
+ BYTE* const wkspStart = (BYTE*)workspace;
+ BYTE* const wkspEnd = wkspStart + wkspSize;
+ BYTE* const countWkspStart = wkspStart;
+ unsigned* const countWksp = (unsigned*)workspace;
+ const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
+ BYTE* const nodeWksp = countWkspStart + countWkspSize;
+ const size_t nodeWkspSize = wkspEnd-nodeWksp;
+ unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;
+ unsigned huffLog = HUF_TABLELOG_DEFAULT;
+ HUF_repeat repeat = prevHuf->repeatMode;
+ DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_literals (srcSize=%zu)", srcSize);
+
+ /* Prepare nextEntropy assuming reusing the existing table */
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+
+ if (disableLiteralsCompression) {
+ DEBUGLOG(5, "set_basic - disabled");
+ hufMetadata->hType = set_basic;
+ return 0;
+ }
+
+ /* small ? don't even attempt compression (speed opt) */
+#ifndef COMPRESS_LITERALS_SIZE_MIN
+#define COMPRESS_LITERALS_SIZE_MIN 63
+#endif
+ { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
+ if (srcSize <= minLitSize) {
+ DEBUGLOG(5, "set_basic - too small");
+ hufMetadata->hType = set_basic;
+ return 0;
+ }
+ }
+
+ /* Scan input and build symbol stats */
+ { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
+ FORWARD_IF_ERROR(largest, "HIST_count_wksp failed");
+ if (largest == srcSize) {
+ DEBUGLOG(5, "set_rle");
+ hufMetadata->hType = set_rle;
+ return 0;
+ }
+ if (largest <= (srcSize >> 7)+4) {
+ DEBUGLOG(5, "set_basic - no gain");
+ hufMetadata->hType = set_basic;
+ return 0;
+ }
+ }
+
+ /* Validate the previous Huffman table */
+ if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {
+ repeat = HUF_repeat_none;
+ }
+
+ /* Build Huffman Tree */
+ ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
+ huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
+ { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
+ maxSymbolValue, huffLog,
+ nodeWksp, nodeWkspSize);
+ FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp");
+ huffLog = (U32)maxBits;
+ { /* Build and write the CTable */
+ size_t const newCSize = HUF_estimateCompressedSize(
+ (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
+ size_t const hSize = HUF_writeCTable_wksp(
+ hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
+ (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,
+ nodeWksp, nodeWkspSize);
+ /* Check against repeating the previous CTable */
+ if (repeat != HUF_repeat_none) {
+ size_t const oldCSize = HUF_estimateCompressedSize(
+ (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
+ if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
+ DEBUGLOG(5, "set_repeat - smaller");
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+ hufMetadata->hType = set_repeat;
+ return 0;
+ }
+ }
+ if (newCSize + hSize >= srcSize) {
+ DEBUGLOG(5, "set_basic - no gains");
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+ hufMetadata->hType = set_basic;
+ return 0;
+ }
+ DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
+ hufMetadata->hType = set_compressed;
+ nextHuf->repeatMode = HUF_repeat_check;
+ return hSize;
+ }
+ }
+}
+
+
+/* ZSTD_buildDummySequencesStatistics():
+ * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic,
+ * and updates nextEntropy to the appropriate repeatMode.
+ */
+static ZSTD_symbolEncodingTypeStats_t
+ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) {
+ ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0};
+ nextEntropy->litlength_repeatMode = FSE_repeat_none;
+ nextEntropy->offcode_repeatMode = FSE_repeat_none;
+ nextEntropy->matchlength_repeatMode = FSE_repeat_none;
+ return stats;
+}
+
+/** ZSTD_buildBlockEntropyStats_sequences() :
+ * Builds entropy for the sequences.
+ * Stores symbol compression modes and fse table to fseMetadata.
+ * Requires ENTROPY_WORKSPACE_SIZE wksp.
+ * @return : size of fse tables or error code */
+static size_t ZSTD_buildBlockEntropyStats_sequences(seqStore_t* seqStorePtr,
+ const ZSTD_fseCTables_t* prevEntropy,
+ ZSTD_fseCTables_t* nextEntropy,
+ const ZSTD_CCtx_params* cctxParams,
+ ZSTD_fseCTablesMetadata_t* fseMetadata,
+ void* workspace, size_t wkspSize)
{
- ZSTD_compressedBlockState_t* const tmp = zc->blockState.prevCBlock;
- zc->blockState.prevCBlock = zc->blockState.nextCBlock;
- zc->blockState.nextCBlock = tmp;
+ ZSTD_strategy const strategy = cctxParams->cParams.strategy;
+ size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
+ BYTE* const ostart = fseMetadata->fseTablesBuffer;
+ BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
+ BYTE* op = ostart;
+ unsigned* countWorkspace = (unsigned*)workspace;
+ unsigned* entropyWorkspace = countWorkspace + (MaxSeq + 1);
+ size_t entropyWorkspaceSize = wkspSize - (MaxSeq + 1) * sizeof(*countWorkspace);
+ ZSTD_symbolEncodingTypeStats_t stats;
+
+ DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)", nbSeq);
+ stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
+ prevEntropy, nextEntropy, op, oend,
+ strategy, countWorkspace,
+ entropyWorkspace, entropyWorkspaceSize)
+ : ZSTD_buildDummySequencesStatistics(nextEntropy);
+ FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!");
+ fseMetadata->llType = (symbolEncodingType_e) stats.LLtype;
+ fseMetadata->ofType = (symbolEncodingType_e) stats.Offtype;
+ fseMetadata->mlType = (symbolEncodingType_e) stats.MLtype;
+ fseMetadata->lastCountSize = stats.lastCountSize;
+ return stats.size;
+}
+
+
+/** ZSTD_buildBlockEntropyStats() :
+ * Builds entropy for the block.
+ * Requires workspace size ENTROPY_WORKSPACE_SIZE
+ *
+ * @return : 0 on success or error code
+ */
+size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
+ const ZSTD_entropyCTables_t* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ const ZSTD_CCtx_params* cctxParams,
+ ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+ void* workspace, size_t wkspSize)
+{
+ size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
+ entropyMetadata->hufMetadata.hufDesSize =
+ ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize,
+ &prevEntropy->huf, &nextEntropy->huf,
+ &entropyMetadata->hufMetadata,
+ ZSTD_disableLiteralsCompression(cctxParams),
+ workspace, wkspSize);
+ FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildBlockEntropyStats_literals failed");
+ entropyMetadata->fseMetadata.fseTablesSize =
+ ZSTD_buildBlockEntropyStats_sequences(seqStorePtr,
+ &prevEntropy->fse, &nextEntropy->fse,
+ cctxParams,
+ &entropyMetadata->fseMetadata,
+ workspace, wkspSize);
+ FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildBlockEntropyStats_sequences failed");
+ return 0;
+}
+
+/* Returns the size estimate for the literals section (header + content) of a block */
+static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize,
+ const ZSTD_hufCTables_t* huf,
+ const ZSTD_hufCTablesMetadata_t* hufMetadata,
+ void* workspace, size_t wkspSize,
+ int writeEntropy)
+{
+ unsigned* const countWksp = (unsigned*)workspace;
+ unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;
+ size_t literalSectionHeaderSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB);
+ U32 singleStream = litSize < 256;
+
+ if (hufMetadata->hType == set_basic) return litSize;
+ else if (hufMetadata->hType == set_rle) return 1;
+ else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {
+ size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);
+ if (ZSTD_isError(largest)) return litSize;
+ { size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);
+ if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;
+ if (!singleStream) cLitSizeEstimate += 6; /* multi-stream huffman uses 6-byte jump table */
+ return cLitSizeEstimate + literalSectionHeaderSize;
+ } }
+ assert(0); /* impossible */
+ return 0;
+}
+
+/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */
+static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
+ const BYTE* codeTable, size_t nbSeq, unsigned maxCode,
+ const FSE_CTable* fseCTable,
+ const U32* additionalBits,
+ short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
+ void* workspace, size_t wkspSize)
+{
+ unsigned* const countWksp = (unsigned*)workspace;
+ const BYTE* ctp = codeTable;
+ const BYTE* const ctStart = ctp;
+ const BYTE* const ctEnd = ctStart + nbSeq;
+ size_t cSymbolTypeSizeEstimateInBits = 0;
+ unsigned max = maxCode;
+
+ HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
+ if (type == set_basic) {
+ /* We selected this encoding type, so it must be valid. */
+ assert(max <= defaultMax);
+ (void)defaultMax;
+ cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);
+ } else if (type == set_rle) {
+ cSymbolTypeSizeEstimateInBits = 0;
+ } else if (type == set_compressed || type == set_repeat) {
+ cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);
+ }
+ if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) {
+ return nbSeq * 10;
+ }
+ while (ctp < ctEnd) {
+ if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];
+ else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */
+ ctp++;
+ }
+ return cSymbolTypeSizeEstimateInBits >> 3;
+}
+
+/* Returns the size estimate for the sequences section (header + content) of a block */
+static size_t ZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable,
+ const BYTE* llCodeTable,
+ const BYTE* mlCodeTable,
+ size_t nbSeq,
+ const ZSTD_fseCTables_t* fseTables,
+ const ZSTD_fseCTablesMetadata_t* fseMetadata,
+ void* workspace, size_t wkspSize,
+ int writeEntropy)
+{
+ size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ);
+ size_t cSeqSizeEstimate = 0;
+ cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff,
+ fseTables->offcodeCTable, NULL,
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
+ workspace, wkspSize);
+ cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL,
+ fseTables->litlengthCTable, LL_bits,
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
+ workspace, wkspSize);
+ cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML,
+ fseTables->matchlengthCTable, ML_bits,
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
+ workspace, wkspSize);
+ if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
+ return cSeqSizeEstimate + sequencesSectionHeaderSize;
+}
+
+/* Returns the size estimate for a given stream of literals, of, ll, ml */
+static size_t ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,
+ const BYTE* ofCodeTable,
+ const BYTE* llCodeTable,
+ const BYTE* mlCodeTable,
+ size_t nbSeq,
+ const ZSTD_entropyCTables_t* entropy,
+ const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+ void* workspace, size_t wkspSize,
+ int writeLitEntropy, int writeSeqEntropy) {
+ size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize,
+ &entropy->huf, &entropyMetadata->hufMetadata,
+ workspace, wkspSize, writeLitEntropy);
+ size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
+ nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
+ workspace, wkspSize, writeSeqEntropy);
+ return seqSize + literalsSize + ZSTD_blockHeaderSize;
+}
+
+/* Builds entropy statistics and uses them for blocksize estimation.
+ *
+ * Returns the estimated compressed size of the seqStore, or a zstd error.
+ */
+static size_t ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, const ZSTD_CCtx* zc) {
+ ZSTD_entropyCTablesMetadata_t entropyMetadata;
+ FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore,
+ &zc->blockState.prevCBlock->entropy,
+ &zc->blockState.nextCBlock->entropy,
+ &zc->appliedParams,
+ &entropyMetadata,
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
+ return ZSTD_estimateBlockSize(seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),
+ seqStore->ofCode, seqStore->llCode, seqStore->mlCode,
+ (size_t)(seqStore->sequences - seqStore->sequencesStart),
+ &zc->blockState.nextCBlock->entropy, &entropyMetadata, zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE,
+ (int)(entropyMetadata.hufMetadata.hType == set_compressed), 1);
+}
+
+/* Returns literals bytes represented in a seqStore */
+static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) {
+ size_t literalsBytes = 0;
+ size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart;
+ size_t i;
+ for (i = 0; i < nbSeqs; ++i) {
+ seqDef seq = seqStore->sequencesStart[i];
+ literalsBytes += seq.litLength;
+ if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) {
+ literalsBytes += 0x10000;
+ }
+ }
+ return literalsBytes;
+}
+
+/* Returns match bytes represented in a seqStore */
+static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) {
+ size_t matchBytes = 0;
+ size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart;
+ size_t i;
+ for (i = 0; i < nbSeqs; ++i) {
+ seqDef seq = seqStore->sequencesStart[i];
+ matchBytes += seq.matchLength + MINMATCH;
+ if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {
+ matchBytes += 0x10000;
+ }
+ }
+ return matchBytes;
+}
+
+/* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx).
+ * Stores the result in resultSeqStore.
+ */
+static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore,
+ const seqStore_t* originalSeqStore,
+ size_t startIdx, size_t endIdx) {
+ BYTE* const litEnd = originalSeqStore->lit;
+ size_t literalsBytes;
+ size_t literalsBytesPreceding = 0;
+
+ *resultSeqStore = *originalSeqStore;
+ if (startIdx > 0) {
+ resultSeqStore->sequences = originalSeqStore->sequencesStart + startIdx;
+ literalsBytesPreceding = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);
+ }
+
+ /* Move longLengthPos into the correct position if necessary */
+ if (originalSeqStore->longLengthType != ZSTD_llt_none) {
+ if (originalSeqStore->longLengthPos < startIdx || originalSeqStore->longLengthPos > endIdx) {
+ resultSeqStore->longLengthType = ZSTD_llt_none;
+ } else {
+ resultSeqStore->longLengthPos -= (U32)startIdx;
+ }
+ }
+ resultSeqStore->sequencesStart = originalSeqStore->sequencesStart + startIdx;
+ resultSeqStore->sequences = originalSeqStore->sequencesStart + endIdx;
+ literalsBytes = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);
+ resultSeqStore->litStart += literalsBytesPreceding;
+ if (endIdx == (size_t)(originalSeqStore->sequences - originalSeqStore->sequencesStart)) {
+ /* This accounts for possible last literals if the derived chunk reaches the end of the block */
+ resultSeqStore->lit = litEnd;
+ } else {
+ resultSeqStore->lit = resultSeqStore->litStart+literalsBytes;
+ }
+ resultSeqStore->llCode += startIdx;
+ resultSeqStore->mlCode += startIdx;
+ resultSeqStore->ofCode += startIdx;
+}
+
+/**
+ * Returns the raw offset represented by the combination of offCode, ll0, and repcode history.
+ * offCode must be an offCode representing a repcode, therefore in the range of [0, 2].
+ */
+static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0) {
+ U32 const adjustedOffCode = offCode + ll0;
+ assert(offCode < ZSTD_REP_NUM);
+ if (adjustedOffCode == ZSTD_REP_NUM) {
+ /* litlength == 0 and offCode == 2 implies selection of first repcode - 1 */
+ assert(rep[0] > 0);
+ return rep[0] - 1;
+ }
+ return rep[adjustedOffCode];
+}
+
+/**
+ * ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise
+ * due to emission of RLE/raw blocks that disturb the offset history, and replaces any repcodes within
+ * the seqStore that may be invalid.
+ *
+ * dRepcodes are updated as would be on the decompression side. cRepcodes are updated exactly in
+ * accordance with the seqStore.
+ */
+static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes,
+ seqStore_t* const seqStore, U32 const nbSeq) {
+ U32 idx = 0;
+ for (; idx < nbSeq; ++idx) {
+ seqDef* const seq = seqStore->sequencesStart + idx;
+ U32 const ll0 = (seq->litLength == 0);
+ U32 offCode = seq->offset - 1;
+ assert(seq->offset > 0);
+ if (offCode <= ZSTD_REP_MOVE) {
+ U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offCode, ll0);
+ U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offCode, ll0);
+ /* Adjust simulated decompression repcode history if we come across a mismatch. Replace
+ * the repcode with the offset it actually references, determined by the compression
+ * repcode history.
+ */
+ if (dRawOffset != cRawOffset) {
+ seq->offset = cRawOffset + ZSTD_REP_NUM;
+ }
+ }
+ /* Compression repcode history is always updated with values directly from the unmodified seqStore.
+ * Decompression repcode history may use modified seq->offset value taken from compression repcode history.
+ */
+ *dRepcodes = ZSTD_updateRep(dRepcodes->rep, seq->offset - 1, ll0);
+ *cRepcodes = ZSTD_updateRep(cRepcodes->rep, offCode, ll0);
+ }
+}
+
+/* ZSTD_compressSeqStore_singleBlock():
+ * Compresses a seqStore into a block with a block header, into the buffer dst.
+ *
+ * Returns the total size of that block (including header) or a ZSTD error code.
+ */
+static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
+ repcodes_t* const dRep, repcodes_t* const cRep,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ U32 lastBlock, U32 isPartition) {
+ const U32 rleMaxLength = 25;
+ BYTE* op = (BYTE*)dst;
+ const BYTE* ip = (const BYTE*)src;
+ size_t cSize;
+ size_t cSeqsSize;
+
+ /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */
+ repcodes_t const dRepOriginal = *dRep;
+ if (isPartition)
+ ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart));
+
+ cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore,
+ &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
+ &zc->appliedParams,
+ op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize,
+ srcSize,
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
+ zc->bmi2);
+ FORWARD_IF_ERROR(cSeqsSize, "ZSTD_entropyCompressSeqStore failed!");
+
+ if (!zc->isFirstBlock &&
+ cSeqsSize < rleMaxLength &&
+ ZSTD_isRLE((BYTE const*)src, srcSize)) {
+ /* We don't want to emit our first block as a RLE even if it qualifies because
+ * doing so will cause the decoder (cli only) to throw a "should consume all input error."
+ * This is only an issue for zstd <= v1.4.3
+ */
+ cSeqsSize = 1;
+ }
+
+ if (zc->seqCollector.collectSequences) {
+ ZSTD_copyBlockSequences(zc);
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
+ return 0;
+ }
+
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+
+ if (cSeqsSize == 0) {
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);
+ FORWARD_IF_ERROR(cSize, "Nocompress block failed");
+ DEBUGLOG(4, "Writing out nocompress block, size: %zu", cSize);
+ *dRep = dRepOriginal; /* reset simulated decompression repcode history */
+ } else if (cSeqsSize == 1) {
+ cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock);
+ FORWARD_IF_ERROR(cSize, "RLE compress block failed");
+ DEBUGLOG(4, "Writing out RLE block, size: %zu", cSize);
+ *dRep = dRepOriginal; /* reset simulated decompression repcode history */
+ } else {
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
+ writeBlockHeader(op, cSeqsSize, srcSize, lastBlock);
+ cSize = ZSTD_blockHeaderSize + cSeqsSize;
+ DEBUGLOG(4, "Writing out compressed block, size: %zu", cSize);
+ }
+ return cSize;
+}
+
+/* Struct to keep track of where we are in our recursive calls. */
+typedef struct {
+ U32* splitLocations; /* Array of split indices */
+ size_t idx; /* The current index within splitLocations being worked on */
+} seqStoreSplits;
+
+#define MIN_SEQUENCES_BLOCK_SPLITTING 300
+#define MAX_NB_SPLITS 196
+
+/* Helper function to perform the recursive search for block splits.
+ * Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half.
+ * If advantageous to split, then we recurse down the two sub-blocks. If not, or if an error occurred in estimation, then
+ * we do not recurse.
+ *
+ * Note: The recursion depth is capped by a heuristic minimum number of sequences, defined by MIN_SEQUENCES_BLOCK_SPLITTING.
+ * In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING).
+ * In practice, recursion depth usually doesn't go beyond 4.
+ *
+ * Furthermore, the number of splits is capped by MAX_NB_SPLITS. At MAX_NB_SPLITS == 196 with the current existing blockSize
+ * maximum of 128 KB, this value is actually impossible to reach.
+ */
+static void ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
+ const ZSTD_CCtx* zc, const seqStore_t* origSeqStore) {
+ seqStore_t fullSeqStoreChunk;
+ seqStore_t firstHalfSeqStore;
+ seqStore_t secondHalfSeqStore;
+ size_t estimatedOriginalSize;
+ size_t estimatedFirstHalfSize;
+ size_t estimatedSecondHalfSize;
+ size_t midIdx = (startIdx + endIdx)/2;
+
+ if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= MAX_NB_SPLITS) {
+ return;
+ }
+ ZSTD_deriveSeqStoreChunk(&fullSeqStoreChunk, origSeqStore, startIdx, endIdx);
+ ZSTD_deriveSeqStoreChunk(&firstHalfSeqStore, origSeqStore, startIdx, midIdx);
+ ZSTD_deriveSeqStoreChunk(&secondHalfSeqStore, origSeqStore, midIdx, endIdx);
+ estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&fullSeqStoreChunk, zc);
+ estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&firstHalfSeqStore, zc);
+ estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&secondHalfSeqStore, zc);
+ DEBUGLOG(5, "Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu",
+ estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize);
+ if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) {
+ return;
+ }
+ if (estimatedFirstHalfSize + estimatedSecondHalfSize < estimatedOriginalSize) {
+ ZSTD_deriveBlockSplitsHelper(splits, startIdx, midIdx, zc, origSeqStore);
+ splits->splitLocations[splits->idx] = (U32)midIdx;
+ splits->idx++;
+ ZSTD_deriveBlockSplitsHelper(splits, midIdx, endIdx, zc, origSeqStore);
+ }
+}
+
+/* Base recursive function. Populates a table with intra-block partition indices that can improve compression ratio.
+ *
+ * Returns the number of splits made (which equals the size of the partition table - 1).
+ */
+static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq) {
+ seqStoreSplits splits = {partitions, 0};
+ if (nbSeq <= 4) {
+ DEBUGLOG(4, "ZSTD_deriveBlockSplits: Too few sequences to split");
+ /* Refuse to try and split anything with less than 4 sequences */
+ return 0;
+ }
+ ZSTD_deriveBlockSplitsHelper(&splits, 0, nbSeq, zc, &zc->seqStore);
+ splits.splitLocations[splits.idx] = nbSeq;
+ DEBUGLOG(5, "ZSTD_deriveBlockSplits: final nb partitions: %zu", splits.idx+1);
+ return splits.idx;
+}
+
+/* ZSTD_compressBlock_splitBlock():
+ * Attempts to split a given block into multiple blocks to improve compression ratio.
+ *
+ * Returns combined size of all blocks (which includes headers), or a ZSTD error code.
+ */
+static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
+ const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq) {
+ size_t cSize = 0;
+ const BYTE* ip = (const BYTE*)src;
+ BYTE* op = (BYTE*)dst;
+ U32 partitions[MAX_NB_SPLITS];
+ size_t i = 0;
+ size_t srcBytesTotal = 0;
+ size_t numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);
+ seqStore_t nextSeqStore;
+ seqStore_t currSeqStore;
+
+ /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history
+ * may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two
+ * separate repcode histories that simulate repcode history on compression and decompression side,
+ * and use the histories to determine whether we must replace a particular repcode with its raw offset.
+ *
+ * 1) cRep gets updated for each partition, regardless of whether the block was emitted as uncompressed
+ * or RLE. This allows us to retrieve the offset value that an invalid repcode references within
+ * a nocompress/RLE block.
+ * 2) dRep gets updated only for compressed partitions, and when a repcode gets replaced, will use
+ * the replacement offset value rather than the original repcode to update the repcode history.
+ * dRep also will be the final repcode history sent to the next block.
+ *
+ * See ZSTD_seqStore_resolveOffCodes() for more details.
+ */
+ repcodes_t dRep;
+ repcodes_t cRep;
+ ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
+ ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
+
+ DEBUGLOG(4, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
+ (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
+ (unsigned)zc->blockState.matchState.nextToUpdate);
+
+ if (numSplits == 0) {
+ size_t cSizeSingleBlock = ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore,
+ &dRep, &cRep,
+ op, dstCapacity,
+ ip, blockSize,
+ lastBlock, 0 /* isPartition */);
+ FORWARD_IF_ERROR(cSizeSingleBlock, "Compressing single block from splitBlock_internal() failed!");
+ DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: No splits");
+ assert(cSizeSingleBlock <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
+ return cSizeSingleBlock;
+ }
+
+ ZSTD_deriveSeqStoreChunk(&currSeqStore, &zc->seqStore, 0, partitions[0]);
+ for (i = 0; i <= numSplits; ++i) {
+ size_t srcBytes;
+ size_t cSizeChunk;
+ U32 const lastPartition = (i == numSplits);
+ U32 lastBlockEntireSrc = 0;
+
+ srcBytes = ZSTD_countSeqStoreLiteralsBytes(&currSeqStore) + ZSTD_countSeqStoreMatchBytes(&currSeqStore);
+ srcBytesTotal += srcBytes;
+ if (lastPartition) {
+ /* This is the final partition, need to account for possible last literals */
+ srcBytes += blockSize - srcBytesTotal;
+ lastBlockEntireSrc = lastBlock;
+ } else {
+ ZSTD_deriveSeqStoreChunk(&nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]);
+ }
+
+ cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, &currSeqStore,
+ &dRep, &cRep,
+ op, dstCapacity,
+ ip, srcBytes,
+ lastBlockEntireSrc, 1 /* isPartition */);
+ DEBUGLOG(5, "Estimated size: %zu actual size: %zu", ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&currSeqStore, zc), cSizeChunk);
+ FORWARD_IF_ERROR(cSizeChunk, "Compressing chunk failed!");
+
+ ip += srcBytes;
+ op += cSizeChunk;
+ dstCapacity -= cSizeChunk;
+ cSize += cSizeChunk;
+ currSeqStore = nextSeqStore;
+ assert(cSizeChunk <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
+ }
+ /* cRep and dRep may have diverged during the compression. If so, we use the dRep repcodes
+ * for the next block.
+ */
+ ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(repcodes_t));
+ return cSize;
+}
+
+static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, U32 lastBlock) {
+ const BYTE* ip = (const BYTE*)src;
+ BYTE* op = (BYTE*)dst;
+ U32 nbSeq;
+ size_t cSize;
+ DEBUGLOG(4, "ZSTD_compressBlock_splitBlock");
+
+ { const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
+ FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
+ if (bss == ZSTDbss_noCompress) {
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+ cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);
+ FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
+ DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block");
+ return cSize;
+ }
+ nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart);
+ }
+
+ assert(zc->appliedParams.splitBlocks == 1);
+ cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq);
+ FORWARD_IF_ERROR(cSize, "Splitting blocks failed!");
+ return cSize;
}
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
@@ -2434,18 +3733,25 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
if (zc->seqCollector.collectSequences) {
ZSTD_copyBlockSequences(zc);
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
return 0;
}
/* encode sequences and literals */
- cSize = ZSTD_compressSequences(&zc->seqStore,
+ cSize = ZSTD_entropyCompressSeqStore(&zc->seqStore,
&zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
&zc->appliedParams,
dst, dstCapacity,
srcSize,
- zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
zc->bmi2);
+ if (zc->seqCollector.collectSequences) {
+ ZSTD_copyBlockSequences(zc);
+ return 0;
+ }
+
+
if (frame &&
/* We don't want to emit our first block as a RLE even if it qualifies because
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
@@ -2461,7 +3767,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
out:
if (!ZSTD_isError(cSize) && cSize > 1) {
- ZSTD_confirmRepcodesAndEntropyTables(zc);
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
}
/* We check that dictionaries have offset codes available for the first
* block. After the first block, the offcode table might not have large
@@ -2514,7 +3820,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
- ZSTD_confirmRepcodesAndEntropyTables(zc);
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
return cSize;
}
}
@@ -2554,9 +3860,9 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
void const* ip,
void const* iend)
{
- if (ZSTD_window_needOverflowCorrection(ms->window, iend)) {
- U32 const maxDist = (U32)1 << params->cParams.windowLog;
- U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
+ U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);
+ U32 const maxDist = (U32)1 << params->cParams.windowLog;
+ if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) {
U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);
ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);
@@ -2579,7 +3885,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
* Frame is supposed already started (header already produced)
* @return : compressed size, or an error code
*/
-static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
+static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
U32 lastFrameChunk)
@@ -2593,7 +3899,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);
- DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
+ DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize);
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
XXH64_update(&cctx->xxhState, src, srcSize);
@@ -2619,6 +3925,10 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_targetCBlockSize failed");
assert(cSize > 0);
assert(cSize <= blockSize + ZSTD_blockHeaderSize);
+ } else if (ZSTD_blockSplitterEnabled(&cctx->appliedParams)) {
+ cSize = ZSTD_compressBlock_splitBlock(cctx, op, dstCapacity, ip, blockSize, lastBlock);
+ FORWARD_IF_ERROR(cSize, "ZSTD_compressBlock_splitBlock failed");
+ assert(cSize > 0 || cctx->seqCollector.collectSequences == 1);
} else {
cSize = ZSTD_compressBlock_internal(cctx,
op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,
@@ -2673,7 +3983,6 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
"dst buf is too small to fit worst-case frame header size.");
DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
!params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);
-
if (params->format == ZSTD_f_zstd1) {
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
pos = 4;
@@ -2699,6 +4008,26 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
return pos;
}
+/* ZSTD_writeSkippableFrame_advanced() :
+ * Writes out a skippable frame with the specified magic number variant (16 are supported),
+ * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data.
+ *
+ * Returns the total number of bytes written, or a ZSTD error code.
+ */
+size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, unsigned magicVariant) {
+ BYTE* op = (BYTE*)dst;
+ RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */,
+ dstSize_tooSmall, "Not enough room for skippable frame");
+ RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, "Src size too large for skippable frame");
+ RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, "Skippable frame magic number variant not supported");
+
+ MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));
+ MEM_writeLE32(op+4, (U32)srcSize);
+ ZSTD_memcpy(op+8, src, srcSize);
+ return srcSize + ZSTD_SKIPPABLEHEADERSIZE;
+}
+
/* ZSTD_writeLastEmptyBlock() :
* output an empty Block with end-of-frame mark to complete a frame
* @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
@@ -2725,6 +4054,7 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe
cctx->externSeqStore.size = nbSeq;
cctx->externSeqStore.capacity = nbSeq;
cctx->externSeqStore.pos = 0;
+ cctx->externSeqStore.posInSequence = 0;
return 0;
}
@@ -2754,11 +4084,12 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
if (!srcSize) return fhSize; /* do not generate an empty block if no input */
- if (!ZSTD_window_update(&ms->window, src, srcSize)) {
+ if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) {
+ ms->forceNonContiguous = 0;
ms->nextToUpdate = ms->window.dictLimit;
}
if (cctx->appliedParams.ldmParams.enableLdm) {
- ZSTD_window_update(&cctx->ldmState.window, src, srcSize);
+ ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0);
}
if (!frame) {
@@ -2826,59 +4157,86 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
{
const BYTE* ip = (const BYTE*) src;
const BYTE* const iend = ip + srcSize;
+ int const loadLdmDict = params->ldmParams.enableLdm && ls != NULL;
+
+ /* Assert that we the ms params match the params we're being given */
+ ZSTD_assertEqualCParams(params->cParams, ms->cParams);
- ZSTD_window_update(&ms->window, src, srcSize);
+ if (srcSize > ZSTD_CHUNKSIZE_MAX) {
+ /* Allow the dictionary to set indices up to exactly ZSTD_CURRENT_MAX.
+ * Dictionaries right at the edge will immediately trigger overflow
+ * correction, but I don't want to insert extra constraints here.
+ */
+ U32 const maxDictSize = ZSTD_CURRENT_MAX - 1;
+ /* We must have cleared our windows when our source is this large. */
+ assert(ZSTD_window_isEmpty(ms->window));
+ if (loadLdmDict)
+ assert(ZSTD_window_isEmpty(ls->window));
+ /* If the dictionary is too large, only load the suffix of the dictionary. */
+ if (srcSize > maxDictSize) {
+ ip = iend - maxDictSize;
+ src = ip;
+ srcSize = maxDictSize;
+ }
+ }
+
+ DEBUGLOG(4, "ZSTD_loadDictionaryContent(): useRowMatchFinder=%d", (int)params->useRowMatchFinder);
+ ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0);
ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);
+ ms->forceNonContiguous = params->deterministicRefPrefix;
- if (params->ldmParams.enableLdm && ls != NULL) {
- ZSTD_window_update(&ls->window, src, srcSize);
+ if (loadLdmDict) {
+ ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0);
ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);
}
- /* Assert that we the ms params match the params we're being given */
- ZSTD_assertEqualCParams(params->cParams, ms->cParams);
-
if (srcSize <= HASH_READ_SIZE) return 0;
- while (iend - ip > HASH_READ_SIZE) {
- size_t const remaining = (size_t)(iend - ip);
- size_t const chunk = MIN(remaining, ZSTD_CHUNKSIZE_MAX);
- const BYTE* const ichunk = ip + chunk;
-
- ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, ichunk);
+ ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, iend);
- if (params->ldmParams.enableLdm && ls != NULL)
- ZSTD_ldm_fillHashTable(ls, (const BYTE*)src, (const BYTE*)src + srcSize, &params->ldmParams);
+ if (loadLdmDict)
+ ZSTD_ldm_fillHashTable(ls, ip, iend, &params->ldmParams);
- switch(params->cParams.strategy)
- {
- case ZSTD_fast:
- ZSTD_fillHashTable(ms, ichunk, dtlm);
- break;
- case ZSTD_dfast:
- ZSTD_fillDoubleHashTable(ms, ichunk, dtlm);
- break;
-
- case ZSTD_greedy:
- case ZSTD_lazy:
- case ZSTD_lazy2:
- if (chunk >= HASH_READ_SIZE)
- ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE);
- break;
-
- case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
- case ZSTD_btopt:
- case ZSTD_btultra:
- case ZSTD_btultra2:
- if (chunk >= HASH_READ_SIZE)
- ZSTD_updateTree(ms, ichunk-HASH_READ_SIZE, ichunk);
- break;
+ switch(params->cParams.strategy)
+ {
+ case ZSTD_fast:
+ ZSTD_fillHashTable(ms, iend, dtlm);
+ break;
+ case ZSTD_dfast:
+ ZSTD_fillDoubleHashTable(ms, iend, dtlm);
+ break;
- default:
- assert(0); /* not possible : not a valid strategy id */
+ case ZSTD_greedy:
+ case ZSTD_lazy:
+ case ZSTD_lazy2:
+ assert(srcSize >= HASH_READ_SIZE);
+ if (ms->dedicatedDictSearch) {
+ assert(ms->chainTable != NULL);
+ ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE);
+ } else {
+ assert(params->useRowMatchFinder != ZSTD_urm_auto);
+ if (params->useRowMatchFinder == ZSTD_urm_enableRowMatchFinder) {
+ size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog) * sizeof(U16);
+ ZSTD_memset(ms->tagTable, 0, tagTableSize);
+ ZSTD_row_update(ms, iend-HASH_READ_SIZE);
+ DEBUGLOG(4, "Using row-based hash table for lazy dict");
+ } else {
+ ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);
+ DEBUGLOG(4, "Using chain-based hash table for lazy dict");
+ }
}
+ break;
- ip = ichunk;
+ case ZSTD_btlazy2: /* we want the dictionary table fully sorted */
+ case ZSTD_btopt:
+ case ZSTD_btultra:
+ case ZSTD_btultra2:
+ assert(srcSize >= HASH_READ_SIZE);
+ ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);
+ break;
+
+ default:
+ assert(0); /* not possible : not a valid strategy id */
}
ms->nextToUpdate = (U32)(iend - ms->window.base);
@@ -2887,22 +4245,28 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
/* Dictionaries that assign zero probability to symbols that show up causes problems
- when FSE encoding. Refuse dictionaries that assign zero probability to symbols
- that we may encounter during compression.
- NOTE: This behavior is not standard and could be improved in the future. */
-static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) {
+ * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check
+ * and only dictionaries with 100% valid symbols can be assumed valid.
+ */
+static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)
+{
U32 s;
- RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols");
+ if (dictMaxSymbolValue < maxSymbolValue) {
+ return FSE_repeat_check;
+ }
for (s = 0; s <= maxSymbolValue; ++s) {
- RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols");
+ if (normalizedCounter[s] == 0) {
+ return FSE_repeat_check;
+ }
}
- return 0;
+ return FSE_repeat_valid;
}
size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
- short* offcodeNCount, unsigned* offcodeMaxValue,
const void* const dict, size_t dictSize)
{
+ short offcodeNCount[MaxOff+1];
+ unsigned offcodeMaxValue = MaxOff;
const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */
const BYTE* const dictEnd = dictPtr + dictSize;
dictPtr += 8;
@@ -2924,16 +4288,16 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
}
{ unsigned offcodeLog;
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
- /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
/* fill all offset symbols to avoid garbage at end of table */
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
bs->entropy.fse.offcodeCTable,
offcodeNCount, MaxOff, offcodeLog,
workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted, "");
+ /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */
dictPtr += offcodeHeaderSize;
}
@@ -2942,13 +4306,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
- /* Every match length code must have non-zero probability */
- FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), "");
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
bs->entropy.fse.matchlengthCTable,
matchlengthNCount, matchlengthMaxValue, matchlengthLog,
workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted, "");
+ bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);
dictPtr += matchlengthHeaderSize;
}
@@ -2957,13 +4320,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
- /* Every literal length code must have non-zero probability */
- FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), "");
RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(
bs->entropy.fse.litlengthCTable,
litlengthNCount, litlengthMaxValue, litlengthLog,
workspace, HUF_WORKSPACE_SIZE)),
dictionary_corrupted, "");
+ bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);
dictPtr += litlengthHeaderSize;
}
@@ -2973,12 +4335,28 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
bs->rep[2] = MEM_readLE32(dictPtr+8);
dictPtr += 12;
+ { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
+ U32 offcodeMax = MaxOff;
+ if (dictContentSize <= ((U32)-1) - 128 KB) {
+ U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
+ offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
+ }
+ /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */
+ bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));
+
+ /* All repCodes must be <= dictContentSize and != 0 */
+ { U32 u;
+ for (u=0; u<3; u++) {
+ RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
+ RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
+ } } }
+
return dictPtr - (const BYTE*)dict;
}
/* Dictionary format :
* See :
- * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
+ * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format
*/
/*! ZSTD_loadZstdDictionary() :
* @return : dictID, or an error code
@@ -2995,42 +4373,23 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,
{
const BYTE* dictPtr = (const BYTE*)dict;
const BYTE* const dictEnd = dictPtr + dictSize;
- short offcodeNCount[MaxOff+1];
- unsigned offcodeMaxValue = MaxOff;
size_t dictID;
size_t eSize;
-
ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));
assert(dictSize >= 8);
assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);
dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ );
- eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize);
+ eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);
FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed");
dictPtr += eSize;
- { size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
- U32 offcodeMax = MaxOff;
- if (dictContentSize <= ((U32)-1) - 128 KB) {
- U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
- offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
- }
- /* All offset values <= dictContentSize + 128 KB must be representable */
- FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), "");
- /* All repCodes must be <= dictContentSize and != 0*/
- { U32 u;
- for (u=0; u<3; u++) {
- RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, "");
- RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, "");
- } }
-
- bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid;
- bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid;
- bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid;
+ {
+ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(
ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), "");
- return dictID;
}
+ return dictID;
}
/** ZSTD_compress_insertDictionary() :
@@ -3074,7 +4433,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,
}
#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)
-#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6)
+#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)
/*! ZSTD_compressBegin_internal() :
* @return : 0, or an error code */
@@ -3086,6 +4445,10 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
const ZSTD_CCtx_params* params, U64 pledgedSrcSize,
ZSTD_buffered_policy_e zbuff)
{
+ size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize;
+#if ZSTD_TRACE
+ cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;
+#endif
DEBUGLOG(4, "ZSTD_compressBegin_internal: wlog=%u", params->cParams.windowLog);
/* params are supposed to be fully validated at this point */
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
@@ -3100,13 +4463,14 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);
}
- FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, *params, pledgedSrcSize,
+ FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
+ dictContentSize,
ZSTDcrp_makeClean, zbuff) , "");
{ size_t const dictID = cdict ?
ZSTD_compress_insertDictionary(
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
&cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,
- cdict->dictContentSize, dictContentType, dtlm,
+ cdict->dictContentSize, cdict->dictContentType, dtlm,
cctx->entropyWorkspace)
: ZSTD_compress_insertDictionary(
cctx->blockState.prevCBlock, &cctx->blockState.matchState,
@@ -3115,6 +4479,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
FORWARD_IF_ERROR(dictID, "ZSTD_compress_insertDictionary failed");
assert(dictID <= UINT_MAX);
cctx->dictID = (U32)dictID;
+ cctx->dictContentSize = dictContentSize;
}
return 0;
}
@@ -3143,8 +4508,8 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize)
{
- ZSTD_CCtx_params const cctxParams =
- ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
+ ZSTD_CCtx_params cctxParams;
+ ZSTD_CCtxParams_init_internal(&cctxParams, &params, ZSTD_NO_CLEVEL);
return ZSTD_compressBegin_advanced_internal(cctx,
dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,
NULL /*cdict*/,
@@ -3153,9 +4518,11 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
- ZSTD_CCtx_params const cctxParams =
- ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
+ ZSTD_CCtx_params cctxParams;
+ {
+ ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);
+ ZSTD_CCtxParams_init_internal(&cctxParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);
+ }
DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize);
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,
&cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);
@@ -3209,6 +4576,30 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
return op-ostart;
}
+void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)
+{
+#if ZSTD_TRACE
+ if (cctx->traceCtx && ZSTD_trace_compress_end != NULL) {
+ int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0;
+ ZSTD_Trace trace;
+ ZSTD_memset(&trace, 0, sizeof(trace));
+ trace.version = ZSTD_VERSION_NUMBER;
+ trace.streaming = streaming;
+ trace.dictionaryID = cctx->dictID;
+ trace.dictionarySize = cctx->dictContentSize;
+ trace.uncompressedSize = cctx->consumedSrcSize;
+ trace.compressedSize = cctx->producedCSize + extraCSize;
+ trace.params = &cctx->appliedParams;
+ trace.cctx = cctx;
+ ZSTD_trace_compress_end(cctx->traceCtx, &trace);
+ }
+ cctx->traceCtx = 0;
+#else
+ (void)cctx;
+ (void)extraCSize;
+#endif
+}
+
size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
@@ -3231,26 +4622,10 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
(unsigned)cctx->pledgedSrcSizePlusOne-1,
(unsigned)cctx->consumedSrcSize);
}
+ ZSTD_CCtx_trace(cctx, endResult);
return cSize + endResult;
}
-
-static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const void* dict,size_t dictSize,
- const ZSTD_parameters* params)
-{
- ZSTD_CCtx_params const cctxParams =
- ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, params);
- DEBUGLOG(4, "ZSTD_compress_internal");
- return ZSTD_compress_advanced_internal(cctx,
- dst, dstCapacity,
- src, srcSize,
- dict, dictSize,
- &cctxParams);
-}
-
size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
@@ -3259,11 +4634,12 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
{
DEBUGLOG(4, "ZSTD_compress_advanced");
FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), "");
- return ZSTD_compress_internal(cctx,
- dst, dstCapacity,
- src, srcSize,
- dict, dictSize,
- &params);
+ ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, ZSTD_NO_CLEVEL);
+ return ZSTD_compress_advanced_internal(cctx,
+ dst, dstCapacity,
+ src, srcSize,
+ dict, dictSize,
+ &cctx->simpleApiParams);
}
/* Internal */
@@ -3287,11 +4663,13 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,
const void* dict, size_t dictSize,
int compressionLevel)
{
- ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0);
- ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, &params);
+ {
+ ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);
+ assert(params.fParams.contentSizeFlag == 1);
+ ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);
+ }
DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize);
- assert(params.fParams.contentSizeFlag == 1);
- return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctxParams);
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams);
}
size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
@@ -3309,10 +4687,17 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity,
int compressionLevel)
{
size_t result;
+#if ZSTD_COMPRESS_HEAPMODE
+ ZSTD_CCtx* cctx = ZSTD_createCCtx();
+ RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed");
+ result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);
+ ZSTD_freeCCtx(cctx);
+#else
ZSTD_CCtx ctxBody;
ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);
result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */
+#endif
return result;
}
@@ -3328,14 +4713,17 @@ size_t ZSTD_estimateCDictSize_advanced(
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (unsigned)sizeof(ZSTD_CDict));
return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
- + ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0)
+ /* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small
+ * in case we are using DDS with row-hash. */
+ + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams),
+ /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0)
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
}
size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)
{
- ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);
}
@@ -3353,20 +4741,22 @@ static size_t ZSTD_initCDict_internal(
const void* dictBuffer, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
- ZSTD_compressionParameters cParams)
+ ZSTD_CCtx_params params)
{
DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType);
- assert(!ZSTD_checkCParams(cParams));
- cdict->matchState.cParams = cParams;
+ assert(!ZSTD_checkCParams(params.cParams));
+ cdict->matchState.cParams = params.cParams;
+ cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;
if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {
cdict->dictContent = dictBuffer;
} else {
void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));
RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!");
cdict->dictContent = internalBuffer;
- memcpy(internalBuffer, dictBuffer, dictSize);
+ ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);
}
cdict->dictContentSize = dictSize;
+ cdict->dictContentType = dictContentType;
cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);
@@ -3376,18 +4766,16 @@ static size_t ZSTD_initCDict_internal(
FORWARD_IF_ERROR(ZSTD_reset_matchState(
&cdict->matchState,
&cdict->workspace,
- &cParams,
+ &params.cParams,
+ params.useRowMatchFinder,
ZSTDcrp_makeClean,
ZSTDirp_reset,
ZSTD_resetTarget_CDict), "");
/* (Maybe) load the dictionary
* Skips loading the dictionary if it is < 8 bytes.
*/
- { ZSTD_CCtx_params params;
- memset(&params, 0, sizeof(params));
- params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
+ { params.compressionLevel = ZSTD_CLEVEL_DEFAULT;
params.fParams.contentSizeFlag = 1;
- params.cParams = cParams;
{ size_t const dictID = ZSTD_compress_insertDictionary(
&cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,
&params, cdict->dictContent, cdict->dictContentSize,
@@ -3401,66 +4789,129 @@ static size_t ZSTD_initCDict_internal(
return 0;
}
-ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
+static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictContentType_e dictContentType,
- ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
+ ZSTD_compressionParameters cParams,
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ U32 enableDedicatedDictSearch,
+ ZSTD_customMem customMem)
{
- DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType);
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
{ size_t const workspaceSize =
ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +
ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +
- ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) +
+ ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, enableDedicatedDictSearch, /* forCCtx */ 0) +
(dictLoadMethod == ZSTD_dlm_byRef ? 0
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));
- void* const workspace = ZSTD_malloc(workspaceSize, customMem);
+ void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);
ZSTD_cwksp ws;
ZSTD_CDict* cdict;
if (!workspace) {
- ZSTD_free(workspace, customMem);
+ ZSTD_customFree(workspace, customMem);
return NULL;
}
- ZSTD_cwksp_init(&ws, workspace, workspaceSize);
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
assert(cdict != NULL);
ZSTD_cwksp_move(&cdict->workspace, &ws);
cdict->customMem = customMem;
- cdict->compressionLevel = 0; /* signals advanced API usage */
+ cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */
+ cdict->useRowMatchFinder = useRowMatchFinder;
+ return cdict;
+ }
+}
- if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
- dictBuffer, dictSize,
- dictLoadMethod, dictContentType,
- cParams) )) {
- ZSTD_freeCDict(cdict);
- return NULL;
- }
+ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_compressionParameters cParams,
+ ZSTD_customMem customMem)
+{
+ ZSTD_CCtx_params cctxParams;
+ ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));
+ ZSTD_CCtxParams_init(&cctxParams, 0);
+ cctxParams.cParams = cParams;
+ cctxParams.customMem = customMem;
+ return ZSTD_createCDict_advanced2(
+ dictBuffer, dictSize,
+ dictLoadMethod, dictContentType,
+ &cctxParams, customMem);
+}
+
+ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ const ZSTD_CCtx_params* originalCctxParams,
+ ZSTD_customMem customMem)
+{
+ ZSTD_CCtx_params cctxParams = *originalCctxParams;
+ ZSTD_compressionParameters cParams;
+ ZSTD_CDict* cdict;
- return cdict;
+ DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType);
+ if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+
+ if (cctxParams.enableDedicatedDictSearch) {
+ cParams = ZSTD_dedicatedDictSearch_getCParams(
+ cctxParams.compressionLevel, dictSize);
+ ZSTD_overrideCParams(&cParams, &cctxParams.cParams);
+ } else {
+ cParams = ZSTD_getCParamsFromCCtxParams(
+ &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
+ }
+
+ if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {
+ /* Fall back to non-DDSS params */
+ cctxParams.enableDedicatedDictSearch = 0;
+ cParams = ZSTD_getCParamsFromCCtxParams(
+ &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
+ }
+
+ DEBUGLOG(3, "ZSTD_createCDict_advanced2: DDS: %u", cctxParams.enableDedicatedDictSearch);
+ cctxParams.cParams = cParams;
+ cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);
+
+ cdict = ZSTD_createCDict_advanced_internal(dictSize,
+ dictLoadMethod, cctxParams.cParams,
+ cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,
+ customMem);
+
+ if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
+ dict, dictSize,
+ dictLoadMethod, dictContentType,
+ cctxParams) )) {
+ ZSTD_freeCDict(cdict);
+ return NULL;
}
+
+ return cdict;
}
ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
- ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize,
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
ZSTD_dlm_byCopy, ZSTD_dct_auto,
cParams, ZSTD_defaultCMem);
if (cdict)
- cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
+ cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
return cdict;
}
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
{
- ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize);
- return ZSTD_createCDict_advanced(dict, dictSize,
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);
+ ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,
ZSTD_dlm_byRef, ZSTD_dct_auto,
cParams, ZSTD_defaultCMem);
+ if (cdict)
+ cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;
+ return cdict;
}
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
@@ -3470,7 +4921,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);
ZSTD_cwksp_free(&cdict->workspace, cMem);
if (!cdictInWorkspace) {
- ZSTD_free(cdict, cMem);
+ ZSTD_customFree(cdict, cMem);
}
return 0;
}
@@ -3496,19 +4947,22 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams)
{
- size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0);
+ ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams);
+ /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */
+ size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0);
size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
+ matchStateSize;
ZSTD_CDict* cdict;
+ ZSTD_CCtx_params params;
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
{
ZSTD_cwksp ws;
- ZSTD_cwksp_init(&ws, workspace, workspaceSize);
+ ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);
cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));
if (cdict == NULL) return NULL;
ZSTD_cwksp_move(&cdict->workspace, &ws);
@@ -3518,10 +4972,15 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
(unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize));
if (workspaceSize < neededSize) return NULL;
+ ZSTD_CCtxParams_init(&params, 0);
+ params.cParams = cParams;
+ params.useRowMatchFinder = useRowMatchFinder;
+ cdict->useRowMatchFinder = useRowMatchFinder;
+
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
dict, dictSize,
dictLoadMethod, dictContentType,
- cParams) ))
+ params) ))
return NULL;
return cdict;
@@ -3533,61 +4992,98 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)
return cdict->matchState.cParams;
}
-/* ZSTD_compressBegin_usingCDict_advanced() :
- * cdict must be != NULL */
-size_t ZSTD_compressBegin_usingCDict_advanced(
+/*! ZSTD_getDictID_fromCDict() :
+ * Provides the dictID of the dictionary loaded into `cdict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)
+{
+ if (cdict==NULL) return 0;
+ return cdict->dictID;
+}
+
+/* ZSTD_compressBegin_usingCDict_internal() :
+ * Implementation of various ZSTD_compressBegin_usingCDict* functions.
+ */
+static size_t ZSTD_compressBegin_usingCDict_internal(
ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_advanced");
+ ZSTD_CCtx_params cctxParams;
+ DEBUGLOG(4, "ZSTD_compressBegin_usingCDict_internal");
RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, "NULL pointer!");
- { ZSTD_CCtx_params params = cctx->requestedParams;
+ /* Initialize the cctxParams from the cdict */
+ {
+ ZSTD_parameters params;
+ params.fParams = fParams;
params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF
|| pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER
|| pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN
- || cdict->compressionLevel == 0 )
- && (params.attachDictPref != ZSTD_dictForceLoad) ?
+ || cdict->compressionLevel == 0 ) ?
ZSTD_getCParamsFromCDict(cdict)
: ZSTD_getCParams(cdict->compressionLevel,
pledgedSrcSize,
cdict->dictContentSize);
- /* Increase window log to fit the entire dictionary and source if the
- * source size is known. Limit the increase to 19, which is the
- * window log for compression level 1 with the largest source size.
- */
- if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
- U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
- U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
- params.cParams.windowLog = MAX(params.cParams.windowLog, limitedSrcLog);
- }
- params.fParams = fParams;
- return ZSTD_compressBegin_internal(cctx,
- NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
- cdict,
- &params, pledgedSrcSize,
- ZSTDb_not_buffered);
+ ZSTD_CCtxParams_init_internal(&cctxParams, &params, cdict->compressionLevel);
+ }
+ /* Increase window log to fit the entire dictionary and source if the
+ * source size is known. Limit the increase to 19, which is the
+ * window log for compression level 1 with the largest source size.
+ */
+ if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);
+ U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;
+ cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);
}
+ return ZSTD_compressBegin_internal(cctx,
+ NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,
+ cdict,
+ &cctxParams, pledgedSrcSize,
+ ZSTDb_not_buffered);
+}
+
+
+/* ZSTD_compressBegin_usingCDict_advanced() :
+ * This function is DEPRECATED.
+ * cdict must be != NULL */
+size_t ZSTD_compressBegin_usingCDict_advanced(
+ ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
+ ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
+{
+ return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, pledgedSrcSize);
}
/* ZSTD_compressBegin_usingCDict() :
- * pledgedSrcSize=0 means "unknown"
- * if pledgedSrcSize>0, it will enable contentSizeFlag */
+ * cdict must be != NULL */
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
{
ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
- DEBUGLOG(4, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
- return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
+ return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);
}
-size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
+/*! ZSTD_compress_usingCDict_internal():
+ * Implementation of various ZSTD_compress_usingCDict* functions.
+ */
+static size_t ZSTD_compress_usingCDict_internal(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
{
- FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */
+ FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, srcSize), ""); /* will check if cdict != NULL */
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
}
+/*! ZSTD_compress_usingCDict_advanced():
+ * This function is DEPRECATED.
+ */
+size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
+{
+ return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
+}
+
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary.
* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
@@ -3599,7 +5095,7 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
const ZSTD_CDict* cdict)
{
ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
- return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
+ return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
}
@@ -3640,32 +5136,12 @@ size_t ZSTD_CStreamOutSize(void)
return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
}
-static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx,
- const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType,
- const ZSTD_CDict* const cdict,
- ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize)
+static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)
{
- DEBUGLOG(4, "ZSTD_resetCStream_internal");
- /* Finalize the compression parameters */
- params.cParams = ZSTD_getCParamsFromCCtxParams(&params, pledgedSrcSize, dictSize);
- /* params are supposed to be fully validated at this point */
- assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
- assert(!((dict) && (cdict))); /* either dict or cdict, not both */
-
- FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
- dict, dictSize, dictContentType, ZSTD_dtlm_fast,
- cdict,
- &params, pledgedSrcSize,
- ZSTDb_buffered) , "");
-
- cctx->inToCompress = 0;
- cctx->inBuffPos = 0;
- cctx->inBuffTarget = cctx->blockSize
- + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */
- cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
- cctx->streamStage = zcss_load;
- cctx->frameEnded = 0;
- return 0; /* ready to go */
+ if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))
+ return ZSTD_cpm_attachDict;
+ else
+ return ZSTD_cpm_noAttachDict;
}
/* ZSTD_resetCStream():
@@ -3749,7 +5225,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , "");
FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , "");
FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , "");
- zcs->requestedParams = ZSTD_assignParamsToCCtxParams(&zcs->requestedParams, &params);
+ ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, &params);
FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , "");
return 0;
}
@@ -3815,12 +5291,17 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
/* check expectations */
DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode);
- assert(zcs->inBuff != NULL);
- assert(zcs->inBuffSize > 0);
- assert(zcs->outBuff != NULL);
- assert(zcs->outBuffSize > 0);
+ if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
+ assert(zcs->inBuff != NULL);
+ assert(zcs->inBuffSize > 0);
+ }
+ if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {
+ assert(zcs->outBuff != NULL);
+ assert(zcs->outBuffSize > 0);
+ }
assert(output->pos <= output->size);
assert(input->pos <= input->size);
+ assert((U32)flushMode <= (U32)ZSTD_e_end);
while (someMoreWork) {
switch(zcs->streamStage)
@@ -3830,7 +5311,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
case zcss_load:
if ( (flushMode == ZSTD_e_end)
- && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */
+ && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */
+ || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */
&& (zcs->inBuffPos == 0) ) {
/* shortcut to compression pass directly into output buffer */
size_t const cSize = ZSTD_compressEnd(zcs,
@@ -3843,8 +5325,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
someMoreWork = 0; break;
}
- /* complete loading into inBuffer */
- { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
+ /* complete loading into inBuffer in buffered mode */
+ if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {
+ size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
size_t const loaded = ZSTD_limitCopy(
zcs->inBuff + zcs->inBuffPos, toLoad,
ip, iend-ip);
@@ -3864,31 +5347,49 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
}
/* compress current block (note : this stage cannot be stopped in the middle) */
DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
- { void* cDst;
+ { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);
+ void* cDst;
size_t cSize;
- size_t const iSize = zcs->inBuffPos - zcs->inToCompress;
size_t oSize = oend-op;
- unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
- if (oSize >= ZSTD_compressBound(iSize))
+ size_t const iSize = inputBuffered
+ ? zcs->inBuffPos - zcs->inToCompress
+ : MIN((size_t)(iend - ip), zcs->blockSize);
+ if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)
cDst = op; /* compress into output buffer, to skip flush stage */
else
cDst = zcs->outBuff, oSize = zcs->outBuffSize;
- cSize = lastBlock ?
- ZSTD_compressEnd(zcs, cDst, oSize,
- zcs->inBuff + zcs->inToCompress, iSize) :
- ZSTD_compressContinue(zcs, cDst, oSize,
- zcs->inBuff + zcs->inToCompress, iSize);
- FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
- zcs->frameEnded = lastBlock;
- /* prepare next block */
- zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
- if (zcs->inBuffTarget > zcs->inBuffSize)
- zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
- DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
- (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
- if (!lastBlock)
- assert(zcs->inBuffTarget <= zcs->inBuffSize);
- zcs->inToCompress = zcs->inBuffPos;
+ if (inputBuffered) {
+ unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
+ cSize = lastBlock ?
+ ZSTD_compressEnd(zcs, cDst, oSize,
+ zcs->inBuff + zcs->inToCompress, iSize) :
+ ZSTD_compressContinue(zcs, cDst, oSize,
+ zcs->inBuff + zcs->inToCompress, iSize);
+ FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
+ zcs->frameEnded = lastBlock;
+ /* prepare next block */
+ zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
+ if (zcs->inBuffTarget > zcs->inBuffSize)
+ zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
+ DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
+ (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);
+ if (!lastBlock)
+ assert(zcs->inBuffTarget <= zcs->inBuffSize);
+ zcs->inToCompress = zcs->inBuffPos;
+ } else {
+ unsigned const lastBlock = (ip + iSize == iend);
+ assert(flushMode == ZSTD_e_end /* Already validated */);
+ cSize = lastBlock ?
+ ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) :
+ ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize);
+ /* Consume the input prior to error checking to mirror buffered mode. */
+ if (iSize > 0)
+ ip += iSize;
+ FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed");
+ zcs->frameEnded = lastBlock;
+ if (lastBlock)
+ assert(ip == iend);
+ }
if (cDst == op) { /* no need to flush */
op += cSize;
if (zcs->frameEnded) {
@@ -3905,6 +5406,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
/* fall-through */
case zcss_flush:
DEBUGLOG(5, "flush stage");
+ assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
@@ -3959,6 +5461,135 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
return ZSTD_nextInputSizeHint_MTorST(zcs);
}
+/* After a compression call set the expected input/output buffer.
+ * This is validated at the start of the next compression call.
+ */
+static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input)
+{
+ if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
+ cctx->expectedInBuffer = *input;
+ }
+ if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
+ cctx->expectedOutBufferSize = output->size - output->pos;
+ }
+}
+
+/* Validate that the input/output buffers match the expectations set by
+ * ZSTD_setBufferExpectations.
+ */
+static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
+ ZSTD_outBuffer const* output,
+ ZSTD_inBuffer const* input,
+ ZSTD_EndDirective endOp)
+{
+ if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
+ ZSTD_inBuffer const expect = cctx->expectedInBuffer;
+ if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size)
+ RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!");
+ if (endOp != ZSTD_e_end)
+ RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!");
+ }
+ if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
+ size_t const outBufferSize = output->size - output->pos;
+ if (cctx->expectedOutBufferSize != outBufferSize)
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!");
+ }
+ return 0;
+}
+
+static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
+ ZSTD_EndDirective endOp,
+ size_t inSize) {
+ ZSTD_CCtx_params params = cctx->requestedParams;
+ ZSTD_prefixDict const prefixDict = cctx->prefixDict;
+ FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
+ ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
+ assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
+ if (cctx->cdict && !cctx->localDict.cdict) {
+ /* Let the cdict's compression level take priority over the requested params.
+ * But do not take the cdict's compression level if the "cdict" is actually a localDict
+ * generated from ZSTD_initLocalDict().
+ */
+ params.compressionLevel = cctx->cdict->compressionLevel;
+ }
+ DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
+ if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-fix pledgedSrcSize */
+ {
+ size_t const dictSize = prefixDict.dict
+ ? prefixDict.dictSize
+ : (cctx->cdict ? cctx->cdict->dictContentSize : 0);
+ ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, &params, cctx->pledgedSrcSizePlusOne - 1);
+ params.cParams = ZSTD_getCParamsFromCCtxParams(
+ &params, cctx->pledgedSrcSizePlusOne-1,
+ dictSize, mode);
+ }
+
+ if (ZSTD_CParams_shouldEnableLdm(&params.cParams)) {
+ /* Enable LDM by default for optimal parser and window size >= 128MB */
+ DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)");
+ params.ldmParams.enableLdm = 1;
+ }
+
+ if (ZSTD_CParams_useBlockSplitter(&params.cParams)) {
+ DEBUGLOG(4, "Block splitter enabled by default (window size >= 128K, strategy >= btopt)");
+ params.splitBlocks = 1;
+ }
+
+ params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, &params.cParams);
+
+#ifdef ZSTD_MULTITHREAD
+ if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
+ params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
+ }
+ if (params.nbWorkers > 0) {
+#if ZSTD_TRACE
+ cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;
+#endif
+ /* mt context creation */
+ if (cctx->mtctx == NULL) {
+ DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
+ params.nbWorkers);
+ cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool);
+ RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
+ }
+ /* mt compression */
+ DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
+ FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
+ cctx->mtctx,
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
+ cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
+ cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0;
+ cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize;
+ cctx->consumedSrcSize = 0;
+ cctx->producedCSize = 0;
+ cctx->streamStage = zcss_load;
+ cctx->appliedParams = params;
+ } else
+#endif
+ { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;
+ assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
+ FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,
+ prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,
+ cctx->cdict,
+ &params, pledgedSrcSize,
+ ZSTDb_buffered) , "");
+ assert(cctx->appliedParams.nbWorkers == 0);
+ cctx->inToCompress = 0;
+ cctx->inBuffPos = 0;
+ if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {
+ /* for small input: avoid automatic flush on reaching end of block, since
+ * it would require to add a 3-bytes null block to end frame
+ */
+ cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize);
+ } else {
+ cctx->inBuffTarget = 0;
+ }
+ cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
+ cctx->streamStage = zcss_load;
+ cctx->frameEnded = 0;
+ }
+ return 0;
+}
size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
ZSTD_outBuffer* output,
@@ -3967,82 +5598,69 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
{
DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp);
/* check conditions */
- RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer");
- RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer");
- assert(cctx!=NULL);
+ RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer");
+ RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer");
+ RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective");
+ assert(cctx != NULL);
/* transparent initialization stage */
if (cctx->streamStage == zcss_init) {
- ZSTD_CCtx_params params = cctx->requestedParams;
- ZSTD_prefixDict const prefixDict = cctx->prefixDict;
- FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */
- memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */
- assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */
- DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage");
- if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */
- params.cParams = ZSTD_getCParamsFromCCtxParams(
- &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
-
-
-#ifdef ZSTD_MULTITHREAD
- if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
- params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
- }
- if (params.nbWorkers > 0) {
- /* mt context creation */
- if (cctx->mtctx == NULL) {
- DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u",
- params.nbWorkers);
- cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem);
- RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!");
- }
- /* mt compression */
- DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers);
- FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(
- cctx->mtctx,
- prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
- cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , "");
- cctx->streamStage = zcss_load;
- cctx->appliedParams.nbWorkers = params.nbWorkers;
- } else
-#endif
- { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx,
- prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,
- cctx->cdict,
- params, cctx->pledgedSrcSizePlusOne-1) , "");
- assert(cctx->streamStage == zcss_load);
- assert(cctx->appliedParams.nbWorkers == 0);
- } }
+ FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed");
+ ZSTD_setBufferExpectations(cctx, output, input); /* Set initial buffer expectations now that we've initialized */
+ }
/* end of transparent initialization stage */
+ FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
/* compression stage */
#ifdef ZSTD_MULTITHREAD
if (cctx->appliedParams.nbWorkers > 0) {
- int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
size_t flushMin;
- assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */);
if (cctx->cParamsChanged) {
ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);
cctx->cParamsChanged = 0;
}
- do {
+ for (;;) {
+ size_t const ipos = input->pos;
+ size_t const opos = output->pos;
flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
+ cctx->consumedSrcSize += (U64)(input->pos - ipos);
+ cctx->producedCSize += (U64)(output->pos - opos);
if ( ZSTD_isError(flushMin)
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
+ if (flushMin == 0)
+ ZSTD_CCtx_trace(cctx, 0);
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
}
FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed");
- } while (forceMaxProgress && flushMin != 0 && output->pos < output->size);
+
+ if (endOp == ZSTD_e_continue) {
+ /* We only require some progress with ZSTD_e_continue, not maximal progress.
+ * We're done if we've consumed or produced any bytes, or either buffer is
+ * full.
+ */
+ if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size)
+ break;
+ } else {
+ assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end);
+ /* We require maximal progress. We're done when the flush is complete or the
+ * output buffer is full.
+ */
+ if (flushMin == 0 || output->pos == output->size)
+ break;
+ }
+ }
DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic");
/* Either we don't require maximum forward progress, we've finished the
* flush, or we are out of output space.
*/
- assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
+ assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size);
+ ZSTD_setBufferExpectations(cctx, output, input);
return flushMin;
}
#endif
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
DEBUGLOG(5, "completed ZSTD_compressStream2");
+ ZSTD_setBufferExpectations(cctx, output, input);
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
}
@@ -4065,14 +5683,22 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
+ ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;
+ ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;
DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize);
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
+ /* Enable stable input/output buffers. */
+ cctx->requestedParams.inBufferMode = ZSTD_bm_stable;
+ cctx->requestedParams.outBufferMode = ZSTD_bm_stable;
{ size_t oPos = 0;
size_t iPos = 0;
size_t const result = ZSTD_compressStream2_simpleArgs(cctx,
dst, dstCapacity, &oPos,
src, srcSize, &iPos,
ZSTD_e_end);
+ /* Reset to the original values. */
+ cctx->requestedParams.inBufferMode = originalInBufferMode;
+ cctx->requestedParams.outBufferMode = originalOutBufferMode;
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
if (result != 0) { /* compression not completed, due to lack of output space */
assert(oPos == dstCapacity);
@@ -4083,6 +5709,409 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
}
}
+typedef struct {
+ U32 idx; /* Index in array of ZSTD_Sequence */
+ U32 posInSequence; /* Position within sequence at idx */
+ size_t posInSrc; /* Number of bytes given by sequences provided so far */
+} ZSTD_sequencePosition;
+
+/* Returns a ZSTD error code if sequence is not valid */
+static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
+ size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
+ size_t offsetBound;
+ U32 windowSize = 1 << windowLog;
+ /* posInSrc represents the amount of data the the decoder would decode up to this point.
+ * As long as the amount of data decoded is less than or equal to window size, offsets may be
+ * larger than the total length of output decoded in order to reference the dict, even larger than
+ * window size. After output surpasses windowSize, we're limited to windowSize offsets again.
+ */
+ offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
+ RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
+ RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
+ return 0;
+}
+
+/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */
+static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
+ U32 offCode = rawOffset + ZSTD_REP_MOVE;
+ U32 repCode = 0;
+
+ if (!ll0 && rawOffset == rep[0]) {
+ repCode = 1;
+ } else if (rawOffset == rep[1]) {
+ repCode = 2 - ll0;
+ } else if (rawOffset == rep[2]) {
+ repCode = 3 - ll0;
+ } else if (ll0 && rawOffset == rep[0] - 1) {
+ repCode = 3;
+ }
+ if (repCode) {
+ /* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */
+ offCode = repCode - 1;
+ }
+ return offCode;
+}
+
+/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
+ * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
+ */
+static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
+ const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
+ const void* src, size_t blockSize) {
+ U32 idx = seqPos->idx;
+ BYTE const* ip = (BYTE const*)(src);
+ const BYTE* const iend = ip + blockSize;
+ repcodes_t updatedRepcodes;
+ U32 dictSize;
+ U32 litLength;
+ U32 matchLength;
+ U32 ll0;
+ U32 offCode;
+
+ if (cctx->cdict) {
+ dictSize = (U32)cctx->cdict->dictContentSize;
+ } else if (cctx->prefixDict.dict) {
+ dictSize = (U32)cctx->prefixDict.dictSize;
+ } else {
+ dictSize = 0;
+ }
+ ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
+ for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
+ litLength = inSeqs[idx].litLength;
+ matchLength = inSeqs[idx].matchLength;
+ ll0 = litLength == 0;
+ offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
+ updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
+
+ DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
+ if (cctx->appliedParams.validateSequences) {
+ seqPos->posInSrc += litLength + matchLength;
+ FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
+ cctx->appliedParams.cParams.windowLog, dictSize,
+ cctx->appliedParams.cParams.minMatch),
+ "Sequence validation failed");
+ }
+ RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
+ "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
+ ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
+ ip += matchLength + litLength;
+ }
+ ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
+
+ if (inSeqs[idx].litLength) {
+ DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength);
+ ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);
+ ip += inSeqs[idx].litLength;
+ seqPos->posInSrc += inSeqs[idx].litLength;
+ }
+ RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!");
+ seqPos->idx = idx+1;
+ return 0;
+}
+
+/* Returns the number of bytes to move the current read position back by. Only non-zero
+ * if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something
+ * went wrong.
+ *
+ * This function will attempt to scan through blockSize bytes represented by the sequences
+ * in inSeqs, storing any (partial) sequences.
+ *
+ * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
+ * avoid splitting a match, or to avoid splitting a match such that it would produce a match
+ * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
+ */
+static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
+ const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
+ const void* src, size_t blockSize) {
+ U32 idx = seqPos->idx;
+ U32 startPosInSequence = seqPos->posInSequence;
+ U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
+ size_t dictSize;
+ BYTE const* ip = (BYTE const*)(src);
+ BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */
+ repcodes_t updatedRepcodes;
+ U32 bytesAdjustment = 0;
+ U32 finalMatchSplit = 0;
+ U32 litLength;
+ U32 matchLength;
+ U32 rawOffset;
+ U32 offCode;
+
+ if (cctx->cdict) {
+ dictSize = cctx->cdict->dictContentSize;
+ } else if (cctx->prefixDict.dict) {
+ dictSize = cctx->prefixDict.dictSize;
+ } else {
+ dictSize = 0;
+ }
+ DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize);
+ DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
+ ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
+ while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
+ const ZSTD_Sequence currSeq = inSeqs[idx];
+ litLength = currSeq.litLength;
+ matchLength = currSeq.matchLength;
+ rawOffset = currSeq.offset;
+
+ /* Modify the sequence depending on where endPosInSequence lies */
+ if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
+ if (startPosInSequence >= litLength) {
+ startPosInSequence -= litLength;
+ litLength = 0;
+ matchLength -= startPosInSequence;
+ } else {
+ litLength -= startPosInSequence;
+ }
+ /* Move to the next sequence */
+ endPosInSequence -= currSeq.litLength + currSeq.matchLength;
+ startPosInSequence = 0;
+ idx++;
+ } else {
+ /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence
+ does not reach the end of the match. So, we have to split the sequence */
+ DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u",
+ currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);
+ if (endPosInSequence > litLength) {
+ U32 firstHalfMatchLength;
+ litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;
+ firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;
+ if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {
+ /* Only ever split the match if it is larger than the block size */
+ U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;
+ if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {
+ /* Move the endPosInSequence backward so that it creates match of minMatch length */
+ endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
+ bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;
+ firstHalfMatchLength -= bytesAdjustment;
+ }
+ matchLength = firstHalfMatchLength;
+ /* Flag that we split the last match - after storing the sequence, exit the loop,
+ but keep the value of endPosInSequence */
+ finalMatchSplit = 1;
+ } else {
+ /* Move the position in sequence backwards so that we don't split match, and break to store
+ * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence
+ * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so
+ * would cause the first half of the match to be too small
+ */
+ bytesAdjustment = endPosInSequence - currSeq.litLength;
+ endPosInSequence = currSeq.litLength;
+ break;
+ }
+ } else {
+ /* This sequence ends inside the literals, break to store the last literals */
+ break;
+ }
+ }
+ /* Check if this offset can be represented with a repcode */
+ { U32 ll0 = (litLength == 0);
+ offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
+ updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
+ }
+
+ if (cctx->appliedParams.validateSequences) {
+ seqPos->posInSrc += litLength + matchLength;
+ FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
+ cctx->appliedParams.cParams.windowLog, dictSize,
+ cctx->appliedParams.cParams.minMatch),
+ "Sequence validation failed");
+ }
+ DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
+ RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
+ "Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
+ ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
+ ip += matchLength + litLength;
+ }
+ DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
+ assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);
+ seqPos->idx = idx;
+ seqPos->posInSequence = endPosInSequence;
+ ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
+
+ iend -= bytesAdjustment;
+ if (ip != iend) {
+ /* Store any last literals */
+ U32 lastLLSize = (U32)(iend - ip);
+ assert(ip <= iend);
+ DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize);
+ ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);
+ seqPos->posInSrc += lastLLSize;
+ }
+
+ return bytesAdjustment;
+}
+
+typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
+ const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
+ const void* src, size_t blockSize);
+static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
+ ZSTD_sequenceCopier sequenceCopier = NULL;
+ assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
+ if (mode == ZSTD_sf_explicitBlockDelimiters) {
+ return ZSTD_copySequencesToSeqStoreExplicitBlockDelim;
+ } else if (mode == ZSTD_sf_noBlockDelimiters) {
+ return ZSTD_copySequencesToSeqStoreNoBlockDelim;
+ }
+ assert(sequenceCopier != NULL);
+ return sequenceCopier;
+}
+
+/* Compress, block-by-block, all of the sequences given.
+ *
+ * Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error.
+ */
+static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
+ const void* src, size_t srcSize) {
+ size_t cSize = 0;
+ U32 lastBlock;
+ size_t blockSize;
+ size_t compressedSeqsSize;
+ size_t remaining = srcSize;
+ ZSTD_sequencePosition seqPos = {0, 0, 0};
+
+ BYTE const* ip = (BYTE const*)src;
+ BYTE* op = (BYTE*)dst;
+ ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
+
+ DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
+ /* Special case: empty frame */
+ if (remaining == 0) {
+ U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header");
+ MEM_writeLE32(op, cBlockHeader24);
+ op += ZSTD_blockHeaderSize;
+ dstCapacity -= ZSTD_blockHeaderSize;
+ cSize += ZSTD_blockHeaderSize;
+ }
+
+ while (remaining) {
+ size_t cBlockSize;
+ size_t additionalByteAdjustment;
+ lastBlock = remaining <= cctx->blockSize;
+ blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize;
+ ZSTD_resetSeqStore(&cctx->seqStore);
+ DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize);
+
+ additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize);
+ FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
+ blockSize -= additionalByteAdjustment;
+
+ /* If blocks are too small, emit as a nocompress block */
+ if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) {
+ cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
+ FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
+ DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize);
+ cSize += cBlockSize;
+ ip += blockSize;
+ op += cBlockSize;
+ remaining -= blockSize;
+ dstCapacity -= cBlockSize;
+ continue;
+ }
+
+ compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore,
+ &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,
+ &cctx->appliedParams,
+ op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,
+ blockSize,
+ cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
+ cctx->bmi2);
+ FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed");
+ DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize);
+
+ if (!cctx->isFirstBlock &&
+ ZSTD_maybeRLE(&cctx->seqStore) &&
+ ZSTD_isRLE((BYTE const*)src, srcSize)) {
+ /* We don't want to emit our first block as a RLE even if it qualifies because
+ * doing so will cause the decoder (cli only) to throw a "should consume all input error."
+ * This is only an issue for zstd <= v1.4.3
+ */
+ compressedSeqsSize = 1;
+ }
+
+ if (compressedSeqsSize == 0) {
+ /* ZSTD_noCompressBlock writes the block header as well */
+ cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);
+ FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed");
+ DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize);
+ } else if (compressedSeqsSize == 1) {
+ cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);
+ FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed");
+ DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize);
+ } else {
+ U32 cBlockHeader;
+ /* Error checking and repcodes update */
+ ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState);
+ if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+ cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+
+ /* Write block header into beginning of block*/
+ cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);
+ MEM_writeLE24(op, cBlockHeader);
+ cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;
+ DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize);
+ }
+
+ cSize += cBlockSize;
+ DEBUGLOG(4, "cSize running total: %zu", cSize);
+
+ if (lastBlock) {
+ break;
+ } else {
+ ip += blockSize;
+ op += cBlockSize;
+ remaining -= blockSize;
+ dstCapacity -= cBlockSize;
+ cctx->isFirstBlock = 0;
+ }
+ }
+
+ return cSize;
+}
+
+size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
+ const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
+ const void* src, size_t srcSize) {
+ BYTE* op = (BYTE*)dst;
+ size_t cSize = 0;
+ size_t compressedBlocksSize = 0;
+ size_t frameHeaderSize = 0;
+
+ /* Transparent initialization stage, same as compressStream2() */
+ DEBUGLOG(3, "ZSTD_compressSequences()");
+ assert(cctx != NULL);
+ FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed");
+ /* Begin writing output, starting with frame header */
+ frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID);
+ op += frameHeaderSize;
+ dstCapacity -= frameHeaderSize;
+ cSize += frameHeaderSize;
+ if (cctx->appliedParams.fParams.checksumFlag && srcSize) {
+ XXH64_update(&cctx->xxhState, src, srcSize);
+ }
+ /* cSize includes block header size and compressed sequences size */
+ compressedBlocksSize = ZSTD_compressSequences_internal(cctx,
+ op, dstCapacity,
+ inSeqs, inSeqsSize,
+ src, srcSize);
+ FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!");
+ cSize += compressedBlocksSize;
+ dstCapacity -= compressedBlocksSize;
+
+ if (cctx->appliedParams.fParams.checksumFlag) {
+ U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
+ RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum");
+ DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum);
+ MEM_writeLE32((char*)dst + cSize, checksum);
+ cSize += 4;
+ }
+
+ DEBUGLOG(3, "Final compressed size: %zu", cSize);
+ return cSize;
+}
+
/*====== Finalize ======*/
/*! ZSTD_flushStream() :
@@ -4115,6 +6144,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
#define ZSTD_MAX_CLEVEL 22
int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
+int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; }
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
{ /* "default" - for any srcSize > 256 KB */
@@ -4223,25 +6253,110 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
},
};
+static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
+{
+ ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
+ switch (cParams.strategy) {
+ case ZSTD_fast:
+ case ZSTD_dfast:
+ break;
+ case ZSTD_greedy:
+ case ZSTD_lazy:
+ case ZSTD_lazy2:
+ cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;
+ break;
+ case ZSTD_btlazy2:
+ case ZSTD_btopt:
+ case ZSTD_btultra:
+ case ZSTD_btultra2:
+ break;
+ }
+ return cParams;
+}
+
+static int ZSTD_dedicatedDictSearch_isSupported(
+ ZSTD_compressionParameters const* cParams)
+{
+ return (cParams->strategy >= ZSTD_greedy)
+ && (cParams->strategy <= ZSTD_lazy2)
+ && (cParams->hashLog > cParams->chainLog)
+ && (cParams->chainLog <= 24);
+}
+
+/**
+ * Reverses the adjustment applied to cparams when enabling dedicated dict
+ * search. This is used to recover the params set to be used in the working
+ * context. (Otherwise, those tables would also grow.)
+ */
+static void ZSTD_dedicatedDictSearch_revertCParams(
+ ZSTD_compressionParameters* cParams) {
+ switch (cParams->strategy) {
+ case ZSTD_fast:
+ case ZSTD_dfast:
+ break;
+ case ZSTD_greedy:
+ case ZSTD_lazy:
+ case ZSTD_lazy2:
+ cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;
+ if (cParams->hashLog < ZSTD_HASHLOG_MIN) {
+ cParams->hashLog = ZSTD_HASHLOG_MIN;
+ }
+ break;
+ case ZSTD_btlazy2:
+ case ZSTD_btopt:
+ case ZSTD_btultra:
+ case ZSTD_btultra2:
+ break;
+ }
+}
+
+static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
+{
+ switch (mode) {
+ case ZSTD_cpm_unknown:
+ case ZSTD_cpm_noAttachDict:
+ case ZSTD_cpm_createCDict:
+ break;
+ case ZSTD_cpm_attachDict:
+ dictSize = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ { int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
+ size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
+ return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
+ }
+}
+
/*! ZSTD_getCParams_internal() :
* @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.
* Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.
- * Use dictSize == 0 for unknown or unused. */
-static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
+ * Use dictSize == 0 for unknown or unused.
+ * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */
+static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode)
{
- int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;
- size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;
- U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;
+ U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);
- int row = compressionLevel;
+ int row;
DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel);
+
+ /* row */
if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */
- if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
- if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
+ else if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */
+ else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;
+ else row = compressionLevel;
+
{ ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];
- if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */
+ DEBUGLOG(5, "ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u", tableID, row, (U32)cp.strategy);
+ /* acceleration factor */
+ if (compressionLevel < 0) {
+ int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);
+ cp.targetLength = (unsigned)(-clampedCompressionLevel);
+ }
/* refine parameters based on srcSize & dictSize */
- return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize);
+ return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode);
}
}
@@ -4251,18 +6366,18 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel,
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
{
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
- return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
+ return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
}
/*! ZSTD_getParams() :
* same idea as ZSTD_getCParams()
* @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).
* Fields of `ZSTD_frameParameters` are set to default values */
-static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
+static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) {
ZSTD_parameters params;
- ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize);
+ ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);
DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel);
- memset(&params, 0, sizeof(params));
+ ZSTD_memset(&params, 0, sizeof(params));
params.cParams = cParams;
params.fParams.contentSizeFlag = 1;
return params;
@@ -4274,5 +6389,5 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned lo
* Fields of `ZSTD_frameParameters` are set to default values */
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
- return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize);
+ return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_internal.h b/Utilities/cmzstd/lib/compress/zstd_compress_internal.h
index db73f6ce2..3b04fd09f 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_internal.h
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -28,7 +28,6 @@
extern "C" {
#endif
-
/*-*************************************
* Constants
***************************************/
@@ -64,7 +63,7 @@ typedef struct {
} ZSTD_localDict;
typedef struct {
- U32 CTable[HUF_CTABLE_SIZE_U32(255)];
+ HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)];
HUF_repeat repeatMode;
} ZSTD_hufCTables_t;
@@ -82,12 +81,76 @@ typedef struct {
ZSTD_fseCTables_t fse;
} ZSTD_entropyCTables_t;
+/***********************************************
+* Entropy buffer statistics structs and funcs *
+***********************************************/
+/** ZSTD_hufCTablesMetadata_t :
+ * Stores Literals Block Type for a super-block in hType, and
+ * huffman tree description in hufDesBuffer.
+ * hufDesSize refers to the size of huffman tree description in bytes.
+ * This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */
typedef struct {
- U32 off;
- U32 len;
+ symbolEncodingType_e hType;
+ BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
+ size_t hufDesSize;
+} ZSTD_hufCTablesMetadata_t;
+
+/** ZSTD_fseCTablesMetadata_t :
+ * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
+ * fse tables in fseTablesBuffer.
+ * fseTablesSize refers to the size of fse tables in bytes.
+ * This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */
+typedef struct {
+ symbolEncodingType_e llType;
+ symbolEncodingType_e ofType;
+ symbolEncodingType_e mlType;
+ BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
+ size_t fseTablesSize;
+ size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
+} ZSTD_fseCTablesMetadata_t;
+
+typedef struct {
+ ZSTD_hufCTablesMetadata_t hufMetadata;
+ ZSTD_fseCTablesMetadata_t fseMetadata;
+} ZSTD_entropyCTablesMetadata_t;
+
+/** ZSTD_buildBlockEntropyStats() :
+ * Builds entropy for the block.
+ * @return : 0 on success or error code */
+size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
+ const ZSTD_entropyCTables_t* prevEntropy,
+ ZSTD_entropyCTables_t* nextEntropy,
+ const ZSTD_CCtx_params* cctxParams,
+ ZSTD_entropyCTablesMetadata_t* entropyMetadata,
+ void* workspace, size_t wkspSize);
+
+/*********************************
+* Compression internals structs *
+*********************************/
+
+typedef struct {
+ U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
+ U32 len; /* Raw length of match */
} ZSTD_match_t;
typedef struct {
+ U32 offset; /* Offset of sequence */
+ U32 litLength; /* Length of literals prior to match */
+ U32 matchLength; /* Raw length of match */
+} rawSeq;
+
+typedef struct {
+ rawSeq* seq; /* The start of the sequences */
+ size_t pos; /* The index in seq where reading stopped. pos <= size. */
+ size_t posInSequence; /* The position within the sequence at seq[pos] where reading
+ stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */
+ size_t size; /* The number of sequences. <= capacity. */
+ size_t capacity; /* The capacity starting from `seq` pointer */
+} rawSeqStore_t;
+
+UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
+
+typedef struct {
int price;
U32 off;
U32 mlen;
@@ -125,14 +188,21 @@ typedef struct {
} ZSTD_compressedBlockState_t;
typedef struct {
- BYTE const* nextSrc; /* next block here to continue on current prefix */
- BYTE const* base; /* All regular indexes relative to this position */
- BYTE const* dictBase; /* extDict indexes relative to this position */
- U32 dictLimit; /* below that point, need extDict */
- U32 lowLimit; /* below that point, no more valid data */
+ BYTE const* nextSrc; /* next block here to continue on current prefix */
+ BYTE const* base; /* All regular indexes relative to this position */
+ BYTE const* dictBase; /* extDict indexes relative to this position */
+ U32 dictLimit; /* below that point, need extDict */
+ U32 lowLimit; /* below that point, no more valid data */
+ U32 nbOverflowCorrections; /* Number of times overflow correction has run since
+ * ZSTD_window_init(). Useful for debugging coredumps
+ * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.
+ */
} ZSTD_window_t;
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
+
+#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
+
struct ZSTD_matchState_t {
ZSTD_window_t window; /* State for window round buffer management */
U32 loadedDictEnd; /* index of end of dictionary, within context's referential.
@@ -144,12 +214,24 @@ struct ZSTD_matchState_t {
*/
U32 nextToUpdate; /* index from which to continue table update */
U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */
+
+ U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
+ U16* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */
+ U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
+
U32* hashTable;
U32* hashTable3;
U32* chainTable;
+
+ U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */
+
+ int dedicatedDictSearch; /* Indicates whether this matchState is using the
+ * dedicated dictionary search structure.
+ */
optState_t opt; /* optimal parser state */
const ZSTD_matchState_t* dictMatchState;
ZSTD_compressionParameters cParams;
+ const rawSeqStore_t* ldmSeqStore;
};
typedef struct {
@@ -164,12 +246,21 @@ typedef struct {
} ldmEntry_t;
typedef struct {
+ BYTE const* split;
+ U32 hash;
+ U32 checksum;
+ ldmEntry_t* bucket;
+} ldmMatchCandidate_t;
+
+#define LDM_BATCH_SIZE 64
+
+typedef struct {
ZSTD_window_t window; /* State for the window round buffer management */
ldmEntry_t* hashTable;
U32 loadedDictEnd;
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
- U64 hashPower; /* Used to compute the rolling hash.
- * Depends on ldmParams.minMatchLength */
+ size_t splitIndices[LDM_BATCH_SIZE];
+ ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];
} ldmState_t;
typedef struct {
@@ -182,19 +273,6 @@ typedef struct {
} ldmParams_t;
typedef struct {
- U32 offset;
- U32 litLength;
- U32 matchLength;
-} rawSeq;
-
-typedef struct {
- rawSeq* seq; /* The start of the sequences */
- size_t pos; /* The position where reading stopped. <= size. */
- size_t size; /* The number of sequences. <= capacity. */
- size_t capacity; /* The capacity starting from `seq` pointer */
-} rawSeqStore_t;
-
-typedef struct {
int collectSequences;
ZSTD_Sequence* seqStart;
size_t seqIndex;
@@ -228,17 +306,52 @@ struct ZSTD_CCtx_params_s {
/* Long distance matching parameters */
ldmParams_t ldmParams;
+ /* Dedicated dict search algorithm trigger */
+ int enableDedicatedDictSearch;
+
+ /* Input/output buffer modes */
+ ZSTD_bufferMode_e inBufferMode;
+ ZSTD_bufferMode_e outBufferMode;
+
+ /* Sequence compression API */
+ ZSTD_sequenceFormat_e blockDelimiters;
+ int validateSequences;
+
+ /* Block splitting */
+ int splitBlocks;
+
+ /* Param for deciding whether to use row-based matchfinder */
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder;
+
+ /* Always load a dictionary in ext-dict mode (not prefix mode)? */
+ int deterministicRefPrefix;
+
/* Internal use, for createCCtxParams() and freeCCtxParams() only */
ZSTD_customMem customMem;
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
+#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
+#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)
+
+/**
+ * Indicates whether this compression proceeds directly from user-provided
+ * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
+ * whether the context needs to buffer the input/output (ZSTDb_buffered).
+ */
+typedef enum {
+ ZSTDb_not_buffered,
+ ZSTDb_buffered
+} ZSTD_buffered_policy_e;
+
struct ZSTD_CCtx_s {
ZSTD_compressionStage_e stage;
int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
ZSTD_CCtx_params requestedParams;
ZSTD_CCtx_params appliedParams;
+ ZSTD_CCtx_params simpleApiParams; /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */
U32 dictID;
+ size_t dictContentSize;
ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
size_t blockSize;
@@ -247,6 +360,7 @@ struct ZSTD_CCtx_s {
unsigned long long producedCSize;
XXH64_state_t xxhState;
ZSTD_customMem customMem;
+ ZSTD_threadPool* pool;
size_t staticSize;
SeqCollector seqCollector;
int isFirstBlock;
@@ -258,7 +372,10 @@ struct ZSTD_CCtx_s {
size_t maxNbLdmSequences;
rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
ZSTD_blockState_t blockState;
- U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */
+ U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
+
+ /* Wether we are streaming or not */
+ ZSTD_buffered_policy_e bufferedPolicy;
/* streaming */
char* inBuff;
@@ -273,6 +390,10 @@ struct ZSTD_CCtx_s {
ZSTD_cStreamStage streamStage;
U32 frameEnded;
+ /* Stable in/out buffer verification */
+ ZSTD_inBuffer expectedInBuffer;
+ size_t expectedOutBufferSize;
+
/* Dictionary */
ZSTD_localDict localDict;
const ZSTD_CDict* cdict;
@@ -282,17 +403,46 @@ struct ZSTD_CCtx_s {
#ifdef ZSTD_MULTITHREAD
ZSTDMT_CCtx* mtctx;
#endif
+
+ /* Tracing */
+#if ZSTD_TRACE
+ ZSTD_TraceCtx traceCtx;
+#endif
};
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
-typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e;
-
+typedef enum {
+ ZSTD_noDict = 0,
+ ZSTD_extDict = 1,
+ ZSTD_dictMatchState = 2,
+ ZSTD_dedicatedDictSearch = 3
+} ZSTD_dictMode_e;
+
+typedef enum {
+ ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict.
+ * In this mode we use both the srcSize and the dictSize
+ * when selecting and adjusting parameters.
+ */
+ ZSTD_cpm_attachDict = 1, /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.
+ * In this mode we only take the srcSize into account when selecting
+ * and adjusting parameters.
+ */
+ ZSTD_cpm_createCDict = 2, /* Creating a CDict.
+ * In this mode we take both the source size and the dictionary size
+ * into account when selecting and adjusting the parameters.
+ */
+ ZSTD_cpm_unknown = 3, /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
+ * We don't know what these parameters are for. We default to the legacy
+ * behavior of taking both the source size and the dict size into account
+ * when selecting and adjusting parameters.
+ */
+} ZSTD_cParamMode_e;
typedef size_t (*ZSTD_blockCompressor) (
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
@@ -345,7 +495,7 @@ MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 con
newReps.rep[1] = rep[0];
newReps.rep[0] = currentOffset;
} else { /* repCode == 0 */
- memcpy(&newReps, rep, sizeof(newReps));
+ ZSTD_memcpy(&newReps, rep, sizeof(newReps));
}
}
return newReps;
@@ -372,7 +522,7 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi
RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
dstSize_tooSmall, "dst buf too small for uncompressed block");
MEM_writeLE24(dst, cBlockHeader24);
- memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
+ ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
return ZSTD_blockHeaderSize + srcSize;
}
@@ -469,8 +619,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
/* literal Length */
if (litLength>0xFFFF) {
- assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
- seqStorePtr->longLengthID = 1;
+ assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
+ seqStorePtr->longLengthType = ZSTD_llt_literalLength;
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
}
seqStorePtr->sequences[0].litLength = (U16)litLength;
@@ -480,8 +630,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
/* match Length */
if (mlBase>0xFFFF) {
- assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
- seqStorePtr->longLengthID = 2;
+ assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
+ seqStorePtr->longLengthType = ZSTD_llt_matchLength;
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
}
seqStorePtr->sequences[0].matchLength = (U16)mlBase;
@@ -498,8 +648,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
if (MEM_isLittleEndian()) {
if (MEM_64bits()) {
# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
+# if STATIC_BMI2
+ return _tzcnt_u64(val) >> 3;
+# else
+ unsigned long r = 0;
+ return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
+# endif
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_ctzll((U64)val) >> 3);
# else
@@ -530,8 +684,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
} else { /* Big Endian CPU */
if (MEM_64bits()) {
# if defined(_MSC_VER) && defined(_WIN64)
- unsigned long r = 0;
- return _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0;
+# if STATIC_BMI2
+ return _lzcnt_u64(val) >> 3;
+# else
+ unsigned long r = 0;
+ return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
+# endif
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_clzll(val) >> 3);
# else
@@ -626,7 +784,8 @@ static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
-MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
+MEM_STATIC FORCE_INLINE_ATTR
+size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
{
switch(mls)
{
@@ -723,6 +882,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
window->dictLimit = end;
}
+MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
+{
+ return window.dictLimit == 1 &&
+ window.lowLimit == 1 &&
+ (window.nextSrc - window.base) == 1;
+}
+
/**
* ZSTD_window_hasExtDict():
* Returns non-zero if the window has a non-empty extDict.
@@ -742,20 +908,74 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
return ZSTD_window_hasExtDict(ms->window) ?
ZSTD_extDict :
ms->dictMatchState != NULL ?
- ZSTD_dictMatchState :
+ (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :
ZSTD_noDict;
}
+/* Defining this macro to non-zero tells zstd to run the overflow correction
+ * code much more frequently. This is very inefficient, and should only be
+ * used for tests and fuzzers.
+ */
+#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY
+# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1
+# else
+# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0
+# endif
+#endif
+
+/**
+ * ZSTD_window_canOverflowCorrect():
+ * Returns non-zero if the indices are large enough for overflow correction
+ * to work correctly without impacting compression ratio.
+ */
+MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
+ U32 cycleLog,
+ U32 maxDist,
+ U32 loadedDictEnd,
+ void const* src)
+{
+ U32 const cycleSize = 1u << cycleLog;
+ U32 const curr = (U32)((BYTE const*)src - window.base);
+ U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize);
+
+ /* Adjust the min index to backoff the overflow correction frequency,
+ * so we don't waste too much CPU in overflow correction. If this
+ * computation overflows we don't really care, we just need to make
+ * sure it is at least minIndexToOverflowCorrect.
+ */
+ U32 const adjustment = window.nbOverflowCorrections + 1;
+ U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,
+ minIndexToOverflowCorrect);
+ U32 const indexLargeEnough = curr > adjustedIndex;
+
+ /* Only overflow correct early if the dictionary is invalidated already,
+ * so we don't hurt compression ratio.
+ */
+ U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;
+
+ return indexLargeEnough && dictionaryInvalidated;
+}
+
/**
* ZSTD_window_needOverflowCorrection():
* Returns non-zero if the indices are getting too large and need overflow
* protection.
*/
MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
+ U32 cycleLog,
+ U32 maxDist,
+ U32 loadedDictEnd,
+ void const* src,
void const* srcEnd)
{
- U32 const current = (U32)((BYTE const*)srcEnd - window.base);
- return current > ZSTD_CURRENT_MAX;
+ U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
+ if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
+ if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {
+ return 1;
+ }
+ }
+ return curr > ZSTD_CURRENT_MAX;
}
/**
@@ -766,7 +986,6 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
*
* The least significant cycleLog bits of the indices must remain the same,
* which may be 0. Every index up to maxDist in the past must be valid.
- * NOTE: (maxDist & cycleMask) must be zero.
*/
MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
U32 maxDist, void const* src)
@@ -790,17 +1009,25 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
* 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
* windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
*/
- U32 const cycleMask = (1U << cycleLog) - 1;
- U32 const current = (U32)((BYTE const*)src - window->base);
- U32 const currentCycle0 = current & cycleMask;
+ U32 const cycleSize = 1u << cycleLog;
+ U32 const cycleMask = cycleSize - 1;
+ U32 const curr = (U32)((BYTE const*)src - window->base);
+ U32 const currentCycle0 = curr & cycleMask;
/* Exclude zero so that newCurrent - maxDist >= 1. */
- U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0;
- U32 const newCurrent = currentCycle1 + maxDist;
- U32 const correction = current - newCurrent;
- assert((maxDist & cycleMask) == 0);
- assert(current > newCurrent);
- /* Loose bound, should be around 1<<29 (see above) */
- assert(correction > 1<<28);
+ U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0;
+ U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize);
+ U32 const correction = curr - newCurrent;
+ /* maxDist must be a power of two so that:
+ * (newCurrent & cycleMask) == (curr & cycleMask)
+ * This is required to not corrupt the chains / binary tree.
+ */
+ assert((maxDist & (maxDist - 1)) == 0);
+ assert((curr & cycleMask) == (newCurrent & cycleMask));
+ assert(curr > newCurrent);
+ if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
+ /* Loose bound, should be around 1<<29 (see above) */
+ assert(correction > 1<<28);
+ }
window->base += correction;
window->dictBase += correction;
@@ -816,6 +1043,8 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
assert(window->lowLimit <= newCurrent);
assert(window->dictLimit <= newCurrent);
+ ++window->nbOverflowCorrections;
+
DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
window->lowLimit);
return correction;
@@ -919,12 +1148,13 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window,
}
MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
- memset(window, 0, sizeof(*window));
+ ZSTD_memset(window, 0, sizeof(*window));
window->base = (BYTE const*)"";
window->dictBase = (BYTE const*)"";
window->dictLimit = 1; /* start from 1, so that 1st position is valid */
window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
window->nextSrc = window->base + 1; /* see issue #1241 */
+ window->nbOverflowCorrections = 0;
}
/**
@@ -935,7 +1165,8 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
* Returns non-zero if the segment is contiguous.
*/
MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
- void const* src, size_t srcSize)
+ void const* src, size_t srcSize,
+ int forceNonContiguous)
{
BYTE const* const ip = (BYTE const*)src;
U32 contiguous = 1;
@@ -945,7 +1176,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
assert(window->base != NULL);
assert(window->dictBase != NULL);
/* Check if blocks follow each other */
- if (src != window->nextSrc) {
+ if (src != window->nextSrc || forceNonContiguous) {
/* not contiguous */
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
@@ -973,12 +1204,16 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
/**
* Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.
*/
-MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog)
+MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
{
U32 const maxDistance = 1U << windowLog;
U32 const lowestValid = ms->window.lowLimit;
- U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid;
+ U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
U32 const isDictionary = (ms->loadedDictEnd != 0);
+ /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
+ * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
+ * valid for the entire block. So this check is sufficient to find the lowest valid match index.
+ */
U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
return matchLowest;
}
@@ -986,12 +1221,15 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current
/**
* Returns the lowest allowed match index in the prefix.
*/
-MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog)
+MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
{
U32 const maxDistance = 1U << windowLog;
U32 const lowestValid = ms->window.dictLimit;
- U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid;
+ U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
U32 const isDictionary = (ms->loadedDictEnd != 0);
+ /* When computing the lowest prefix index we need to take the dictionary into account to handle
+ * the edge case where the dictionary and the source are contiguous in memory.
+ */
U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
return matchLowest;
}
@@ -1045,7 +1283,6 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
* assumptions : magic number supposed already checked
* and dictSize >= 8 */
size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
- short* offcodeNCount, unsigned* offcodeMaxValue,
const void* const dict, size_t dictSize);
void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
@@ -1061,7 +1298,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
* Note: srcSizeHint == 0 means 0!
*/
ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
- const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize);
+ const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
/*! ZSTD_initCStream_internal() :
* Private use only. Init streaming operation.
@@ -1122,4 +1359,9 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe
* condition for correct operation : hashLog > 1 */
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
+/** ZSTD_CCtx_trace() :
+ * Trace the end of a compression call.
+ */
+void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
+
#endif /* ZSTD_COMPRESS_H */
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_literals.c b/Utilities/cmzstd/lib/compress/zstd_compress_literals.c
index 17e7168d8..008337bb1 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_literals.c
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_literals.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -15,7 +15,7 @@
size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const ostart = (BYTE*)dst;
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, "");
@@ -35,14 +35,14 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src,
assert(0);
}
- memcpy(ostart + flSize, src, srcSize);
+ ZSTD_memcpy(ostart + flSize, src, srcSize);
DEBUGLOG(5, "Raw literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize));
return srcSize + flSize;
}
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
{
- BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const ostart = (BYTE*)dst;
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
@@ -86,7 +86,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
disableLiteralCompression, (U32)srcSize);
/* Prepare nextEntropy assuming reusing the existing table */
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
if (disableLiteralCompression)
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
@@ -117,12 +117,12 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
}
}
- if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+ if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
}
if (cLitSize==1) {
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
+ ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_literals.h b/Utilities/cmzstd/lib/compress/zstd_compress_literals.h
index 8b0870574..9904c0cd3 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_literals.h
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_literals.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_sequences.c b/Utilities/cmzstd/lib/compress/zstd_compress_sequences.c
index f9f8097c8..611eabdcb 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_sequences.c
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_sequences.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -51,6 +51,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {
}
/**
+ * Returns true if we should use ncount=-1 else we should
+ * use ncount=1 for low probability symbols instead.
+ */
+static unsigned ZSTD_useLowProbCount(size_t const nbSeq)
+{
+ /* Heuristic: This should cover most blocks <= 16K and
+ * start to fade out after 16K to about 32K depending on
+ * comprssibility.
+ */
+ return nbSeq >= 2048;
+}
+
+/**
* Returns the cost in bytes of encoding the normalized count header.
* Returns an error if any of the helper functions return an error.
*/
@@ -60,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,
BYTE wksp[FSE_NCOUNTBOUND];
S16 norm[MaxSeq + 1];
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), "");
+ FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), "");
return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);
}
@@ -72,6 +85,8 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
{
unsigned cost = 0;
unsigned s;
+
+ assert(total > 0);
for (s = 0; s <= max; ++s) {
unsigned norm = (unsigned)((256 * count[s]) / total);
if (count[s] != 0 && norm == 0)
@@ -219,6 +234,11 @@ ZSTD_selectEncodingType(
return set_compressed;
}
+typedef struct {
+ S16 norm[MaxSeq + 1];
+ U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)];
+} ZSTD_BuildCTableWksp;
+
size_t
ZSTD_buildCTable(void* dst, size_t dstCapacity,
FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
@@ -239,13 +259,13 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
*op = codeTable[0];
return 1;
case set_repeat:
- memcpy(nextCTable, prevCTable, prevCTableSize);
+ ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize);
return 0;
case set_basic:
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */
return 0;
case set_compressed: {
- S16 norm[MaxSeq + 1];
+ ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace;
size_t nbSeq_1 = nbSeq;
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
if (count[codeTable[nbSeq-1]] > 1) {
@@ -253,10 +273,12 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
nbSeq_1--;
}
assert(nbSeq_1 > 1);
- FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), "");
- { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
+ assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp));
+ (void)entropyWorkspaceSize;
+ FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
+ { size_t const NCountSize = FSE_writeNCount(op, oend - op, wksp->norm, max, tableLog); /* overflow protected */
FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
- FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), "");
+ FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), "");
return NCountSize;
}
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_sequences.h b/Utilities/cmzstd/lib/compress/zstd_compress_sequences.h
index 68c6f9a5a..7991364c2 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_sequences.h
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_sequences.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_superblock.c b/Utilities/cmzstd/lib/compress/zstd_compress_superblock.c
index b693866c0..e4e45069b 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_superblock.c
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_superblock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -15,288 +15,10 @@
#include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
#include "hist.h" /* HIST_countFast_wksp */
-#include "zstd_compress_internal.h"
+#include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */
#include "zstd_compress_sequences.h"
#include "zstd_compress_literals.h"
-/*-*************************************
-* Superblock entropy buffer structs
-***************************************/
-/** ZSTD_hufCTablesMetadata_t :
- * Stores Literals Block Type for a super-block in hType, and
- * huffman tree description in hufDesBuffer.
- * hufDesSize refers to the size of huffman tree description in bytes.
- * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
-typedef struct {
- symbolEncodingType_e hType;
- BYTE hufDesBuffer[500]; /* TODO give name to this value */
- size_t hufDesSize;
-} ZSTD_hufCTablesMetadata_t;
-
-/** ZSTD_fseCTablesMetadata_t :
- * Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
- * fse tables in fseTablesBuffer.
- * fseTablesSize refers to the size of fse tables in bytes.
- * This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */
-typedef struct {
- symbolEncodingType_e llType;
- symbolEncodingType_e ofType;
- symbolEncodingType_e mlType;
- BYTE fseTablesBuffer[500]; /* TODO give name to this value */
- size_t fseTablesSize;
- size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
-} ZSTD_fseCTablesMetadata_t;
-
-typedef struct {
- ZSTD_hufCTablesMetadata_t hufMetadata;
- ZSTD_fseCTablesMetadata_t fseMetadata;
-} ZSTD_entropyCTablesMetadata_t;
-
-
-/** ZSTD_buildSuperBlockEntropy_literal() :
- * Builds entropy for the super-block literals.
- * Stores literals block type (raw, rle, compressed, repeat) and
- * huffman description table to hufMetadata.
- * @return : size of huffman description table or error code */
-static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize,
- const ZSTD_hufCTables_t* prevHuf,
- ZSTD_hufCTables_t* nextHuf,
- ZSTD_hufCTablesMetadata_t* hufMetadata,
- const int disableLiteralsCompression,
- void* workspace, size_t wkspSize)
-{
- BYTE* const wkspStart = (BYTE*)workspace;
- BYTE* const wkspEnd = wkspStart + wkspSize;
- BYTE* const countWkspStart = wkspStart;
- unsigned* const countWksp = (unsigned*)workspace;
- const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
- BYTE* const nodeWksp = countWkspStart + countWkspSize;
- const size_t nodeWkspSize = wkspEnd-nodeWksp;
- unsigned maxSymbolValue = 255;
- unsigned huffLog = HUF_TABLELOG_DEFAULT;
- HUF_repeat repeat = prevHuf->repeatMode;
-
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
-
- /* Prepare nextEntropy assuming reusing the existing table */
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
-
- if (disableLiteralsCompression) {
- DEBUGLOG(5, "set_basic - disabled");
- hufMetadata->hType = set_basic;
- return 0;
- }
-
- /* small ? don't even attempt compression (speed opt) */
-# define COMPRESS_LITERALS_SIZE_MIN 63
- { size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
- if (srcSize <= minLitSize) {
- DEBUGLOG(5, "set_basic - too small");
- hufMetadata->hType = set_basic;
- return 0;
- }
- }
-
- /* Scan input and build symbol stats */
- { size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
- FORWARD_IF_ERROR(largest, "HIST_count_wksp failed");
- if (largest == srcSize) {
- DEBUGLOG(5, "set_rle");
- hufMetadata->hType = set_rle;
- return 0;
- }
- if (largest <= (srcSize >> 7)+4) {
- DEBUGLOG(5, "set_basic - no gain");
- hufMetadata->hType = set_basic;
- return 0;
- }
- }
-
- /* Validate the previous Huffman table */
- if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {
- repeat = HUF_repeat_none;
- }
-
- /* Build Huffman Tree */
- memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
- huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
- { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
- maxSymbolValue, huffLog,
- nodeWksp, nodeWkspSize);
- FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp");
- huffLog = (U32)maxBits;
- { /* Build and write the CTable */
- size_t const newCSize = HUF_estimateCompressedSize(
- (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
- size_t const hSize = HUF_writeCTable(
- hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
- (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog);
- /* Check against repeating the previous CTable */
- if (repeat != HUF_repeat_none) {
- size_t const oldCSize = HUF_estimateCompressedSize(
- (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
- if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
- DEBUGLOG(5, "set_repeat - smaller");
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
- hufMetadata->hType = set_repeat;
- return 0;
- }
- }
- if (newCSize + hSize >= srcSize) {
- DEBUGLOG(5, "set_basic - no gains");
- memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
- hufMetadata->hType = set_basic;
- return 0;
- }
- DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
- hufMetadata->hType = set_compressed;
- nextHuf->repeatMode = HUF_repeat_check;
- return hSize;
- }
- }
-}
-
-/** ZSTD_buildSuperBlockEntropy_sequences() :
- * Builds entropy for the super-block sequences.
- * Stores symbol compression modes and fse table to fseMetadata.
- * @return : size of fse tables or error code */
-static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
- const ZSTD_fseCTables_t* prevEntropy,
- ZSTD_fseCTables_t* nextEntropy,
- const ZSTD_CCtx_params* cctxParams,
- ZSTD_fseCTablesMetadata_t* fseMetadata,
- void* workspace, size_t wkspSize)
-{
- BYTE* const wkspStart = (BYTE*)workspace;
- BYTE* const wkspEnd = wkspStart + wkspSize;
- BYTE* const countWkspStart = wkspStart;
- unsigned* const countWksp = (unsigned*)workspace;
- const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned);
- BYTE* const cTableWksp = countWkspStart + countWkspSize;
- const size_t cTableWkspSize = wkspEnd-cTableWksp;
- ZSTD_strategy const strategy = cctxParams->cParams.strategy;
- FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
- FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
- FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
- const BYTE* const ofCodeTable = seqStorePtr->ofCode;
- const BYTE* const llCodeTable = seqStorePtr->llCode;
- const BYTE* const mlCodeTable = seqStorePtr->mlCode;
- size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
- BYTE* const ostart = fseMetadata->fseTablesBuffer;
- BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
- BYTE* op = ostart;
-
- assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
- memset(workspace, 0, wkspSize);
-
- fseMetadata->lastCountSize = 0;
- /* convert length/distances into codes */
- ZSTD_seqToCodes(seqStorePtr);
- /* build CTable for Literal Lengths */
- { U32 LLtype;
- unsigned max = MaxLL;
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
- DEBUGLOG(5, "Building LL table");
- nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
- LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
- countWksp, max, mostFrequent, nbSeq,
- LLFSELog, prevEntropy->litlengthCTable,
- LL_defaultNorm, LL_defaultNormLog,
- ZSTD_defaultAllowed, strategy);
- assert(set_basic < set_compressed && set_rle < set_compressed);
- assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
- countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
- prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
- cTableWksp, cTableWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
- if (LLtype == set_compressed)
- fseMetadata->lastCountSize = countSize;
- op += countSize;
- fseMetadata->llType = (symbolEncodingType_e) LLtype;
- } }
- /* build CTable for Offsets */
- { U32 Offtype;
- unsigned max = MaxOff;
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
- /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
- ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
- DEBUGLOG(5, "Building OF table");
- nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
- Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
- countWksp, max, mostFrequent, nbSeq,
- OffFSELog, prevEntropy->offcodeCTable,
- OF_defaultNorm, OF_defaultNormLog,
- defaultPolicy, strategy);
- assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
- countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
- prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
- cTableWksp, cTableWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
- if (Offtype == set_compressed)
- fseMetadata->lastCountSize = countSize;
- op += countSize;
- fseMetadata->ofType = (symbolEncodingType_e) Offtype;
- } }
- /* build CTable for MatchLengths */
- { U32 MLtype;
- unsigned max = MaxML;
- size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
- DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
- nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
- MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
- countWksp, max, mostFrequent, nbSeq,
- MLFSELog, prevEntropy->matchlengthCTable,
- ML_defaultNorm, ML_defaultNormLog,
- ZSTD_defaultAllowed, strategy);
- assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
- { size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
- countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
- prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
- cTableWksp, cTableWkspSize);
- FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
- if (MLtype == set_compressed)
- fseMetadata->lastCountSize = countSize;
- op += countSize;
- fseMetadata->mlType = (symbolEncodingType_e) MLtype;
- } }
- assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer));
- return op-ostart;
-}
-
-
-/** ZSTD_buildSuperBlockEntropy() :
- * Builds entropy for the super-block.
- * @return : 0 on success or error code */
-static size_t
-ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
- const ZSTD_entropyCTables_t* prevEntropy,
- ZSTD_entropyCTables_t* nextEntropy,
- const ZSTD_CCtx_params* cctxParams,
- ZSTD_entropyCTablesMetadata_t* entropyMetadata,
- void* workspace, size_t wkspSize)
-{
- size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
- DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy");
- entropyMetadata->hufMetadata.hufDesSize =
- ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize,
- &prevEntropy->huf, &nextEntropy->huf,
- &entropyMetadata->hufMetadata,
- ZSTD_disableLiteralsCompression(cctxParams),
- workspace, wkspSize);
- FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed");
- entropyMetadata->fseMetadata.fseTablesSize =
- ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr,
- &prevEntropy->fse, &nextEntropy->fse,
- cctxParams,
- &entropyMetadata->fseMetadata,
- workspace, wkspSize);
- FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed");
- return 0;
-}
-
/** ZSTD_compressSubBlock_literal() :
* Compresses literals section for a sub-block.
* When we have to write the Huffman table we will sometimes choose a header
@@ -304,7 +26,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
* before we know the table size + compressed size, so we have a bound on the
* table size. If we guessed incorrectly, we fall back to uncompressed literals.
*
- * We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded
+ * We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
* in writing the header, otherwise it is set to 0.
*
* hufMetadata->hType has literals block type info.
@@ -348,7 +70,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);
if (writeEntropy && hufMetadata->hType == set_compressed) {
- memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
+ ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);
op += hufMetadata->hufDesSize;
cLitSize += hufMetadata->hufDesSize;
DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
@@ -474,7 +196,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables
const U32 MLtype = fseMetadata->mlType;
DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize);
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
- memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
+ ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);
op += fseMetadata->fseTablesSize;
} else {
const U32 repeat = set_repeat;
@@ -603,7 +325,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
const BYTE* codeTable, unsigned maxCode,
size_t nbSeq, const FSE_CTable* fseCTable,
const U32* additionalBits,
- short const* defaultNorm, U32 defaultNormLog,
+ short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
void* workspace, size_t wkspSize)
{
unsigned* const countWksp = (unsigned*)workspace;
@@ -615,7 +337,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */
if (type == set_basic) {
- cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);
+ /* We selected this encoding type, so it must be valid. */
+ assert(max <= defaultMax);
+ cSymbolTypeSizeEstimateInBits = max <= defaultMax
+ ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)
+ : ERROR(GENERIC);
} else if (type == set_rle) {
cSymbolTypeSizeEstimateInBits = 0;
} else if (type == set_compressed || type == set_repeat) {
@@ -639,19 +365,20 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
void* workspace, size_t wkspSize,
int writeEntropy)
{
- size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
+ size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
size_t cSeqSizeEstimate = 0;
+ if (nbSeq == 0) return sequencesSectionHeaderSize;
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
nbSeq, fseTables->offcodeCTable, NULL,
- OF_defaultNorm, OF_defaultNormLog,
+ OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
workspace, wkspSize);
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,
nbSeq, fseTables->litlengthCTable, LL_bits,
- LL_defaultNorm, LL_defaultNormLog,
+ LL_defaultNorm, LL_defaultNormLog, MaxLL,
workspace, wkspSize);
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,
nbSeq, fseTables->matchlengthCTable, ML_bits,
- ML_defaultNorm, ML_defaultNormLog,
+ ML_defaultNorm, ML_defaultNormLog, MaxML,
workspace, wkspSize);
if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
return cSeqSizeEstimate + sequencesSectionHeaderSize;
@@ -790,7 +517,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
} while (!lastSequence);
if (writeLitEntropy) {
DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten");
- memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
+ ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));
}
if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {
/* If we haven't written our entropy tables, then we've violated our contract and
@@ -809,11 +536,11 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
if (sp < send) {
seqDef const* seq;
repcodes_t rep;
- memcpy(&rep, prevCBlock->rep, sizeof(rep));
+ ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
for (seq = sstart; seq < sp; ++seq) {
rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
}
- memcpy(nextCBlock->rep, &rep, sizeof(rep));
+ ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
}
}
DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed");
@@ -826,12 +553,12 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
unsigned lastBlock) {
ZSTD_entropyCTablesMetadata_t entropyMetadata;
- FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore,
+ FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,
&zc->blockState.prevCBlock->entropy,
&zc->blockState.nextCBlock->entropy,
&zc->appliedParams,
&entropyMetadata,
- zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
return ZSTD_compressSubBlock_multi(&zc->seqStore,
zc->blockState.prevCBlock,
@@ -841,5 +568,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
dst, dstCapacity,
src, srcSize,
zc->bmi2, lastBlock,
- zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
+ zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */);
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_compress_superblock.h b/Utilities/cmzstd/lib/compress/zstd_compress_superblock.h
index 07f4cb1dc..176f9b106 100644
--- a/Utilities/cmzstd/lib/compress/zstd_compress_superblock.h
+++ b/Utilities/cmzstd/lib/compress/zstd_compress_superblock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstd_cwksp.h b/Utilities/cmzstd/lib/compress/zstd_cwksp.h
index a25c9263b..2656d26ca 100644
--- a/Utilities/cmzstd/lib/compress/zstd_cwksp.h
+++ b/Utilities/cmzstd/lib/compress/zstd_cwksp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -35,6 +35,10 @@ extern "C" {
#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128
#endif
+
+/* Set our tables and aligneds to align by 64 bytes */
+#define ZSTD_CWKSP_ALIGNMENT_BYTES 64
+
/*-*************************************
* Structures
***************************************/
@@ -45,6 +49,16 @@ typedef enum {
} ZSTD_cwksp_alloc_phase_e;
/**
+ * Used to describe whether the workspace is statically allocated (and will not
+ * necessarily ever be freed), or if it's dynamically allocated and we can
+ * expect a well-formed caller to free this.
+ */
+typedef enum {
+ ZSTD_cwksp_dynamic_alloc,
+ ZSTD_cwksp_static_alloc
+} ZSTD_cwksp_static_alloc_e;
+
+/**
* Zstd fits all its internal datastructures into a single continuous buffer,
* so that it only needs to perform a single OS allocation (or so that a buffer
* can be provided to it and it can perform no allocations at all). This buffer
@@ -92,7 +106,7 @@ typedef enum {
*
* - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,
* so that literally everything fits in a single buffer. Note: if present,
- * this must be the first object in the workspace, since ZSTD_free{CCtx,
+ * this must be the first object in the workspace, since ZSTD_customFree{CCtx,
* CDict}() rely on a pointer comparison to see whether one or two frees are
* required.
*
@@ -107,10 +121,11 @@ typedef enum {
* - Tables: these are any of several different datastructures (hash tables,
* chain tables, binary trees) that all respect a common format: they are
* uint32_t arrays, all of whose values are between 0 and (nextSrc - base).
- * Their sizes depend on the cparams.
+ * Their sizes depend on the cparams. These tables are 64-byte aligned.
*
* - Aligned: these buffers are used for various purposes that require 4 byte
- * alignment, but don't require any initialization before they're used.
+ * alignment, but don't require any initialization before they're used. These
+ * buffers are each aligned to 64 bytes.
*
* - Buffers: these buffers are used for various purposes that don't require
* any alignment or initialization before they're used. This means they can
@@ -123,8 +138,7 @@ typedef enum {
*
* 1. Objects
* 2. Buffers
- * 3. Aligned
- * 4. Tables
+ * 3. Aligned/Tables
*
* Attempts to reserve objects of different types out of order will fail.
*/
@@ -137,9 +151,10 @@ typedef struct {
void* tableValidEnd;
void* allocStart;
- int allocFailed;
+ BYTE allocFailed;
int workspaceOversizedDuration;
ZSTD_cwksp_alloc_phase_e phase;
+ ZSTD_cwksp_static_alloc_e isStatic;
} ZSTD_cwksp;
/*-*************************************
@@ -176,39 +191,123 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
* Since tables aren't currently redzoned, you don't need to call through this
* to figure out how much space you need for the matchState tables. Everything
* else is though.
+ *
+ * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size().
*/
MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+ if (size == 0)
+ return 0;
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
#else
return size;
#endif
}
-MEM_STATIC void ZSTD_cwksp_internal_advance_phase(
+/**
+ * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes.
+ * Used to determine the number of bytes required for a given "aligned".
+ */
+MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
+ return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES));
+}
+
+/**
+ * Returns the amount of additional space the cwksp must allocate
+ * for internal purposes (currently only alignment).
+ */
+MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
+ /* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes
+ * to align the beginning of tables section, as well as another n_2=[0, 63] bytes
+ * to align the beginning of the aligned secion.
+ *
+ * n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and
+ * aligneds being sized in multiples of 64 bytes.
+ */
+ size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES;
+ return slackSpace;
+}
+
+
+/**
+ * Return the number of additional bytes required to align a pointer to the given number of bytes.
+ * alignBytes must be a power of two.
+ */
+MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) {
+ size_t const alignBytesMask = alignBytes - 1;
+ size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask;
+ assert((alignBytes & alignBytesMask) == 0);
+ assert(bytes != ZSTD_CWKSP_ALIGNMENT_BYTES);
+ return bytes;
+}
+
+/**
+ * Internal function. Do not use directly.
+ * Reserves the given number of bytes within the aligned/buffer segment of the wksp, which
+ * counts from the end of the wksp. (as opposed to the object/table segment)
+ *
+ * Returns a pointer to the beginning of that space.
+ */
+MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) {
+ void* const alloc = (BYTE*)ws->allocStart - bytes;
+ void* const bottom = ws->tableEnd;
+ DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
+ alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
+ ZSTD_cwksp_assert_internal_consistency(ws);
+ assert(alloc >= bottom);
+ if (alloc < bottom) {
+ DEBUGLOG(4, "cwksp: alloc failed!");
+ ws->allocFailed = 1;
+ return NULL;
+ }
+ if (alloc < ws->tableValidEnd) {
+ ws->tableValidEnd = alloc;
+ }
+ ws->allocStart = alloc;
+ return alloc;
+}
+
+/**
+ * Moves the cwksp to the next phase, and does any necessary allocations.
+ * Returns a 0 on success, or zstd error
+ */
+MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
assert(phase >= ws->phase);
if (phase > ws->phase) {
+ /* Going from allocating objects to allocating buffers */
if (ws->phase < ZSTD_cwksp_alloc_buffers &&
phase >= ZSTD_cwksp_alloc_buffers) {
ws->tableValidEnd = ws->objectEnd;
}
+
+ /* Going from allocating buffers to allocating aligneds/tables */
if (ws->phase < ZSTD_cwksp_alloc_aligned &&
phase >= ZSTD_cwksp_alloc_aligned) {
- /* If unaligned allocations down from a too-large top have left us
- * unaligned, we need to realign our alloc ptr. Technically, this
- * can consume space that is unaccounted for in the neededSpace
- * calculation. However, I believe this can only happen when the
- * workspace is too large, and specifically when it is too large
- * by a larger margin than the space that will be consumed. */
- /* TODO: cleaner, compiler warning friendly way to do this??? */
- ws->allocStart = (BYTE*)ws->allocStart - ((size_t)ws->allocStart & (sizeof(U32)-1));
- if (ws->allocStart < ws->tableValidEnd) {
- ws->tableValidEnd = ws->allocStart;
+ { /* Align the start of the "aligned" to 64 bytes. Use [1, 64] bytes. */
+ size_t const bytesToAlign =
+ ZSTD_CWKSP_ALIGNMENT_BYTES - ZSTD_cwksp_bytes_to_align_ptr(ws->allocStart, ZSTD_CWKSP_ALIGNMENT_BYTES);
+ DEBUGLOG(5, "reserving aligned alignment addtl space: %zu", bytesToAlign);
+ ZSTD_STATIC_ASSERT((ZSTD_CWKSP_ALIGNMENT_BYTES & (ZSTD_CWKSP_ALIGNMENT_BYTES - 1)) == 0); /* power of 2 */
+ RETURN_ERROR_IF(!ZSTD_cwksp_reserve_internal_buffer_space(ws, bytesToAlign),
+ memory_allocation, "aligned phase - alignment initial allocation failed!");
+ }
+ { /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */
+ void* const alloc = ws->objectEnd;
+ size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);
+ void* const end = (BYTE*)alloc + bytesToAlign;
+ DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign);
+ RETURN_ERROR_IF(end > ws->workspaceEnd, memory_allocation,
+ "table phase - alignment initial allocation failed!");
+ ws->objectEnd = end;
+ ws->tableEnd = end;
+ ws->tableValidEnd = end;
}
}
ws->phase = phase;
+ ZSTD_cwksp_assert_internal_consistency(ws);
}
+ return 0;
}
/**
@@ -224,34 +323,26 @@ MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) {
MEM_STATIC void* ZSTD_cwksp_reserve_internal(
ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
void* alloc;
- void* bottom = ws->tableEnd;
- ZSTD_cwksp_internal_advance_phase(ws, phase);
- alloc = (BYTE *)ws->allocStart - bytes;
+ if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {
+ return NULL;
+ }
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
/* over-reserve space */
- alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
+ bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
#endif
- DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
- alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
- ZSTD_cwksp_assert_internal_consistency(ws);
- assert(alloc >= bottom);
- if (alloc < bottom) {
- DEBUGLOG(4, "cwksp: alloc failed!");
- ws->allocFailed = 1;
- return NULL;
- }
- if (alloc < ws->tableValidEnd) {
- ws->tableValidEnd = alloc;
- }
- ws->allocStart = alloc;
+ alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes);
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
* either size. */
- alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
- __asan_unpoison_memory_region(alloc, bytes);
+ if (alloc) {
+ alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
+ __asan_unpoison_memory_region(alloc, bytes);
+ }
+ }
#endif
return alloc;
@@ -265,28 +356,36 @@ MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) {
}
/**
- * Reserves and returns memory sized on and aligned on sizeof(unsigned).
+ * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
*/
MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
- assert((bytes & (sizeof(U32)-1)) == 0);
- return ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, sizeof(U32)), ZSTD_cwksp_alloc_aligned);
+ void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
+ ZSTD_cwksp_alloc_aligned);
+ assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
+ return ptr;
}
/**
- * Aligned on sizeof(unsigned). These buffers have the special property that
+ * Aligned on 64 bytes. These buffers have the special property that
* their values remain constrained, allowing us to re-use them without
* memset()-ing them.
*/
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
- void* alloc = ws->tableEnd;
- void* end = (BYTE *)alloc + bytes;
- void* top = ws->allocStart;
+ void* alloc;
+ void* end;
+ void* top;
+
+ if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {
+ return NULL;
+ }
+ alloc = ws->tableEnd;
+ end = (BYTE *)alloc + bytes;
+ top = ws->allocStart;
DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining",
alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
assert((bytes & (sizeof(U32)-1)) == 0);
- ZSTD_cwksp_internal_advance_phase(ws, phase);
ZSTD_cwksp_assert_internal_consistency(ws);
assert(end <= top);
if (end > top) {
@@ -296,10 +395,14 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
}
ws->tableEnd = end;
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
- __asan_unpoison_memory_region(alloc, bytes);
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
+ __asan_unpoison_memory_region(alloc, bytes);
+ }
#endif
+ assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
+ assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
return alloc;
}
@@ -311,7 +414,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
void* alloc = ws->objectEnd;
void* end = (BYTE*)alloc + roundedBytes;
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
/* over-reserve space */
end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
#endif
@@ -332,11 +435,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
ws->tableEnd = end;
ws->tableValidEnd = end;
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
* either size. */
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
- __asan_unpoison_memory_region(alloc, bytes);
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
+ __asan_unpoison_memory_region(alloc, bytes);
+ }
#endif
return alloc;
@@ -345,7 +450,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
-#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
+#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
/* To validate that the table re-use logic is sound, and that we don't
* access table space that we haven't cleaned, we re-"poison" the table
* space every time we mark it dirty. */
@@ -380,7 +485,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
assert(ws->tableValidEnd >= ws->objectEnd);
assert(ws->tableValidEnd <= ws->allocStart);
if (ws->tableValidEnd < ws->tableEnd) {
- memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
+ ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd);
}
ZSTD_cwksp_mark_tables_clean(ws);
}
@@ -392,8 +497,12 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {
MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
DEBUGLOG(4, "cwksp: clearing tables!");
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
- {
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+ /* We don't do this when the workspace is statically allocated, because
+ * when that is the case, we have no capability to hook into the end of the
+ * workspace's lifecycle to unpoison the memory.
+ */
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;
__asan_poison_memory_region(ws->objectEnd, size);
}
@@ -410,7 +519,7 @@ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) {
MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
DEBUGLOG(4, "cwksp: clearing!");
-#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
+#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
/* To validate that the context re-use logic is sound, and that we don't
* access stuff that this compression hasn't initialized, we re-"poison"
* the workspace (or at least the non-static, non-table parts of it)
@@ -421,8 +530,12 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
}
#endif
-#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
- {
+#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
+ /* We don't do this when the workspace is statically allocated, because
+ * when that is the case, we have no capability to hook into the end of the
+ * workspace's lifecycle to unpoison the memory.
+ */
+ if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;
__asan_poison_memory_region(ws->objectEnd, size);
}
@@ -442,7 +555,7 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {
* Any existing values in the workspace are ignored (the previously managed
* buffer, if present, must be separately freed).
*/
-MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
+MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) {
DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size);
assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */
ws->workspace = start;
@@ -450,39 +563,45 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) {
ws->objectEnd = ws->workspace;
ws->tableValidEnd = ws->objectEnd;
ws->phase = ZSTD_cwksp_alloc_objects;
+ ws->isStatic = isStatic;
ZSTD_cwksp_clear(ws);
ws->workspaceOversizedDuration = 0;
ZSTD_cwksp_assert_internal_consistency(ws);
}
MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {
- void* workspace = ZSTD_malloc(size, customMem);
+ void* workspace = ZSTD_customMalloc(size, customMem);
DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size);
RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!");
- ZSTD_cwksp_init(ws, workspace, size);
+ ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc);
return 0;
}
MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
void *ptr = ws->workspace;
DEBUGLOG(4, "cwksp: freeing workspace");
- memset(ws, 0, sizeof(ZSTD_cwksp));
- ZSTD_free(ptr, customMem);
+ ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));
+ ZSTD_customFree(ptr, customMem);
}
/**
* Moves the management of a workspace from one cwksp to another. The src cwksp
- * is left in an invalid state (src must be re-init()'ed before its used again).
+ * is left in an invalid state (src must be re-init()'ed before it's used again).
*/
MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
*dst = *src;
- memset(src, 0, sizeof(ZSTD_cwksp));
+ ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));
}
MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {
return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);
}
+MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {
+ return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)
+ + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);
+}
+
MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
return ws->allocFailed;
}
@@ -491,6 +610,24 @@ MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
* Functions Checking Free Space
***************************************/
+/* ZSTD_alignmentSpaceWithinBounds() :
+ * Returns if the estimated space needed for a wksp is within an acceptable limit of the
+ * actual amount of space used.
+ */
+MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp* const ws,
+ size_t const estimatedSpace, int resizedWorkspace) {
+ if (resizedWorkspace) {
+ /* Resized/newly allocated wksp should have exact bounds */
+ return ZSTD_cwksp_used(ws) == estimatedSpace;
+ } else {
+ /* Due to alignment, when reusing a workspace, we can actually consume 63 fewer or more bytes
+ * than estimatedSpace. See the comments in zstd_cwksp.h for details.
+ */
+ return (ZSTD_cwksp_used(ws) >= estimatedSpace - 63) && (ZSTD_cwksp_used(ws) <= estimatedSpace + 63);
+ }
+}
+
+
MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {
return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_double_fast.c b/Utilities/cmzstd/lib/compress/zstd_double_fast.c
index 27eed66cf..d0d3a784d 100644
--- a/Utilities/cmzstd/lib/compress/zstd_double_fast.c
+++ b/Utilities/cmzstd/lib/compress/zstd_double_fast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -31,15 +31,15 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
* is empty.
*/
for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {
- U32 const current = (U32)(ip - base);
+ U32 const curr = (U32)(ip - base);
U32 i;
for (i = 0; i < fastHashFillStep; ++i) {
size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls);
size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8);
if (i == 0)
- hashSmall[smHash] = current + i;
+ hashSmall[smHash] = curr + i;
if (i == 0 || hashLarge[lgHash] == 0)
- hashLarge[lgHash] = current + i;
+ hashLarge[lgHash] = curr + i;
/* Only load extra positions for ZSTD_dtlm_full */
if (dtlm == ZSTD_dtlm_fast)
break;
@@ -108,9 +108,9 @@ size_t ZSTD_compressBlock_doubleFast_generic(
/* init */
ip += (dictAndPrefixLength == 0);
if (dictMode == ZSTD_noDict) {
- U32 const current = (U32)(ip - base);
- U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);
- U32 const maxRep = current - windowLow;
+ U32 const curr = (U32)(ip - base);
+ U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
+ U32 const maxRep = curr - windowLow;
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
}
@@ -129,17 +129,17 @@ size_t ZSTD_compressBlock_doubleFast_generic(
size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);
size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8);
size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls);
- U32 const current = (U32)(ip-base);
+ U32 const curr = (U32)(ip-base);
U32 const matchIndexL = hashLong[h2];
U32 matchIndexS = hashSmall[h];
const BYTE* matchLong = base + matchIndexL;
const BYTE* match = base + matchIndexS;
- const U32 repIndex = current + 1 - offset_1;
+ const U32 repIndex = curr + 1 - offset_1;
const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
&& repIndex < prefixLowestIndex) ?
dictBase + (repIndex - dictIndexDelta) :
base + repIndex;
- hashLong[h2] = hashSmall[h] = current; /* update hash tables */
+ hashLong[h2] = hashSmall[h] = curr; /* update hash tables */
/* check dictMatchState repcode */
if (dictMode == ZSTD_dictMatchState
@@ -177,7 +177,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) {
mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8;
- offset = (U32)(current - dictMatchIndexL - dictIndexDelta);
+ offset = (U32)(curr - dictMatchIndexL - dictIndexDelta);
while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */
goto _match_found;
} }
@@ -209,7 +209,7 @@ _search_next_long:
size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8);
U32 const matchIndexL3 = hashLong[hl3];
const BYTE* matchL3 = base + matchIndexL3;
- hashLong[hl3] = current + 1;
+ hashLong[hl3] = curr + 1;
/* check prefix long +1 match */
if (matchIndexL3 > prefixLowestIndex) {
@@ -228,7 +228,7 @@ _search_next_long:
if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {
mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8;
ip++;
- offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta);
+ offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta);
while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */
goto _match_found;
} } }
@@ -236,7 +236,7 @@ _search_next_long:
/* if no long +1 match, explore the short match we found */
if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
- offset = (U32)(current - matchIndexS);
+ offset = (U32)(curr - matchIndexS);
while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
} else {
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
@@ -260,7 +260,7 @@ _match_stored:
if (ip <= ilimit) {
/* Complementary insertion */
/* done after iLimit test, as candidates could be > iend-8 */
- { U32 const indexToInsert = current+2;
+ { U32 const indexToInsert = curr+2;
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
@@ -401,15 +401,15 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base;
const BYTE* matchLong = matchLongBase + matchLongIndex;
- const U32 current = (U32)(ip-base);
- const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */
+ const U32 curr = (U32)(ip-base);
+ const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */
const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
size_t mLength;
- hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */
+ hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
- & (repIndex > dictStartIndex))
+ & (offset_1 < curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
@@ -421,7 +421,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart;
U32 offset;
mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8;
- offset = current - matchLongIndex;
+ offset = curr - matchLongIndex;
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
@@ -433,19 +433,19 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base;
const BYTE* match3 = match3Base + matchIndex3;
U32 offset;
- hashLong[h3] = current + 1;
+ hashLong[h3] = curr + 1;
if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {
const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend;
const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart;
mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8;
ip++;
- offset = current+1 - matchIndex3;
+ offset = curr+1 - matchIndex3;
while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
} else {
const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;
const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
- offset = current - matchIndex;
+ offset = curr - matchIndex;
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
}
offset_2 = offset_1;
@@ -464,7 +464,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
if (ip <= ilimit) {
/* Complementary insertion */
/* done after iLimit test, as candidates could be > iend-8 */
- { U32 const indexToInsert = current+2;
+ { U32 const indexToInsert = curr+2;
hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
@@ -477,7 +477,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
U32 const repIndex2 = current2 - offset_2;
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
- & (repIndex2 > dictStartIndex))
+ & (offset_2 < current2 - dictStartIndex))
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
diff --git a/Utilities/cmzstd/lib/compress/zstd_double_fast.h b/Utilities/cmzstd/lib/compress/zstd_double_fast.h
index 14d944d69..e16b7b03a 100644
--- a/Utilities/cmzstd/lib/compress/zstd_double_fast.h
+++ b/Utilities/cmzstd/lib/compress/zstd_double_fast.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstd_fast.c b/Utilities/cmzstd/lib/compress/zstd_fast.c
index 85a3a7a91..4edc04dcc 100644
--- a/Utilities/cmzstd/lib/compress/zstd_fast.c
+++ b/Utilities/cmzstd/lib/compress/zstd_fast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -29,16 +29,16 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
* Insert the other positions if their hash entry is empty.
*/
for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {
- U32 const current = (U32)(ip - base);
+ U32 const curr = (U32)(ip - base);
size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls);
- hashTable[hash0] = current;
+ hashTable[hash0] = curr;
if (dtlm == ZSTD_dtlm_fast) continue;
/* Only load extra positions for ZSTD_dtlm_full */
{ U32 p;
for (p = 1; p < fastHashFillStep; ++p) {
size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls);
if (hashTable[hash] == 0) { /* not yet filled */
- hashTable[hash] = current + p;
+ hashTable[hash] = curr + p;
} } } }
}
@@ -72,9 +72,9 @@ ZSTD_compressBlock_fast_generic(
DEBUGLOG(5, "ZSTD_compressBlock_fast_generic");
ip0 += (ip0 == prefixStart);
ip1 = ip0 + 1;
- { U32 const current = (U32)(ip0 - base);
- U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);
- U32 const maxRep = current - windowLow;
+ { U32 const curr = (U32)(ip0 - base);
+ U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
+ U32 const maxRep = curr - windowLow;
if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
}
@@ -242,7 +242,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
assert(endIndex - prefixStartIndex <= maxDistance);
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
- /* ensure there will be no no underflow
+ /* ensure there will be no underflow
* when translating a dict index into a local index */
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
@@ -258,14 +258,14 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
size_t mLength;
size_t const h = ZSTD_hashPtr(ip, hlog, mls);
- U32 const current = (U32)(ip-base);
+ U32 const curr = (U32)(ip-base);
U32 const matchIndex = hashTable[h];
const BYTE* match = base + matchIndex;
- const U32 repIndex = current + 1 - offset_1;
+ const U32 repIndex = curr + 1 - offset_1;
const BYTE* repMatch = (repIndex < prefixStartIndex) ?
dictBase + (repIndex - dictIndexDelta) :
base + repIndex;
- hashTable[h] = current; /* update hash table */
+ hashTable[h] = curr; /* update hash table */
if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
@@ -284,7 +284,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
continue;
} else {
/* found a dict match */
- U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta);
+ U32 const offset = (U32)(curr-dictMatchIndex-dictIndexDelta);
mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4;
while (((ip>anchor) & (dictMatch>dictStart))
&& (ip[-1] == dictMatch[-1])) {
@@ -316,8 +316,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
if (ip <= ilimit) {
/* Fill Table */
- assert(base+current+2 > istart); /* check base overflow */
- hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */
+ assert(base+curr+2 > istart); /* check base overflow */
+ hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; /* here because curr+2 could be > iend-8 */
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
@@ -410,15 +410,15 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
const U32 matchIndex = hashTable[h];
const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;
const BYTE* match = matchBase + matchIndex;
- const U32 current = (U32)(ip-base);
- const U32 repIndex = current + 1 - offset_1;
+ const U32 curr = (U32)(ip-base);
+ const U32 repIndex = curr + 1 - offset_1;
const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- hashTable[h] = current; /* update hash table */
- DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current);
- assert(offset_1 <= current +1); /* check repIndex */
+ hashTable[h] = curr; /* update hash table */
+ DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr);
- if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex))
+ if ( ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */
+ & (offset_1 < curr+1 - dictStartIndex) ) /* note: we are searching at curr+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
@@ -435,7 +435,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
}
{ const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;
const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;
- U32 const offset = current - matchIndex;
+ U32 const offset = curr - matchIndex;
size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
offset_2 = offset_1; offset_1 = offset; /* update offset history */
@@ -446,14 +446,14 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
if (ip <= ilimit) {
/* Fill Table */
- hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2;
+ hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2;
hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base);
/* check immediate repcode */
while (ip <= ilimit) {
U32 const current2 = (U32)(ip-base);
U32 const repIndex2 = current2 - offset_2;
const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */
+ if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 < curr - dictStartIndex)) /* intentional overflow */
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
diff --git a/Utilities/cmzstd/lib/compress/zstd_fast.h b/Utilities/cmzstd/lib/compress/zstd_fast.h
index cf6aaa8e6..0d4a0c109 100644
--- a/Utilities/cmzstd/lib/compress/zstd_fast.h
+++ b/Utilities/cmzstd/lib/compress/zstd_fast.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstd_lazy.c b/Utilities/cmzstd/lib/compress/zstd_lazy.c
index 4cf5c88b5..6ce897dc8 100644
--- a/Utilities/cmzstd/lib/compress/zstd_lazy.c
+++ b/Utilities/cmzstd/lib/compress/zstd_lazy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -58,11 +58,11 @@ ZSTD_updateDUBT(ZSTD_matchState_t* ms,
/** ZSTD_insertDUBT1() :
* sort one already inserted but unsorted position
- * assumption : current >= btlow == (current - btmask)
+ * assumption : curr >= btlow == (curr - btmask)
* doesn't fail */
static void
ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
- U32 current, const BYTE* inputEnd,
+ U32 curr, const BYTE* inputEnd,
U32 nbCompares, U32 btLow,
const ZSTD_dictMode_e dictMode)
{
@@ -74,41 +74,41 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
const BYTE* const base = ms->window.base;
const BYTE* const dictBase = ms->window.dictBase;
const U32 dictLimit = ms->window.dictLimit;
- const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current;
- const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit;
+ const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr;
+ const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* match;
- U32* smallerPtr = bt + 2*(current&btMask);
+ U32* smallerPtr = bt + 2*(curr&btMask);
U32* largerPtr = smallerPtr + 1;
U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */
U32 dummy32; /* to be nullified at the end */
U32 const windowValid = ms->window.lowLimit;
U32 const maxDistance = 1U << cParams->windowLog;
- U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid;
+ U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid;
DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)",
- current, dictLimit, windowLow);
- assert(current >= btLow);
+ curr, dictLimit, windowLow);
+ assert(curr >= btLow);
assert(ip < iend); /* condition for ZSTD_count */
while (nbCompares-- && (matchIndex > windowLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- assert(matchIndex < current);
+ assert(matchIndex < curr);
/* note : all candidates are now supposed sorted,
* but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK
* when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */
if ( (dictMode != ZSTD_extDict)
|| (matchIndex+matchLength >= dictLimit) /* both in current segment*/
- || (current < dictLimit) /* both in extDict */) {
+ || (curr < dictLimit) /* both in extDict */) {
const BYTE* const mBase = ( (dictMode != ZSTD_extDict)
|| (matchIndex+matchLength >= dictLimit)) ?
base : dictBase;
assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */
- || (current < dictLimit) );
+ || (curr < dictLimit) );
match = mBase + matchIndex;
matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);
} else {
@@ -119,7 +119,7 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
}
DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ",
- current, matchIndex, (U32)matchLength);
+ curr, matchIndex, (U32)matchLength);
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */
@@ -168,7 +168,7 @@ ZSTD_DUBT_findBetterDictMatch (
const BYTE* const base = ms->window.base;
const BYTE* const prefixStart = base + ms->window.dictLimit;
- U32 const current = (U32)(ip-base);
+ U32 const curr = (U32)(ip-base);
const BYTE* const dictBase = dms->window.base;
const BYTE* const dictEnd = dms->window.nextSrc;
U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base);
@@ -195,10 +195,10 @@ ZSTD_DUBT_findBetterDictMatch (
if (matchLength > bestLength) {
U32 matchIndex = dictMatchIndex + dictIndexDelta;
- if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)",
- current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex);
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
+ curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + curr - matchIndex, dictMatchIndex, matchIndex);
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
}
if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */
break; /* drop, to guarantee consistency (miss a little bit of compression) */
@@ -218,9 +218,9 @@ ZSTD_DUBT_findBetterDictMatch (
}
if (bestLength >= MINMATCH) {
- U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
- current, (U32)bestLength, (U32)*offsetPtr, mIndex);
+ curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
}
return bestLength;
@@ -241,13 +241,13 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
U32 matchIndex = hashTable[h];
const BYTE* const base = ms->window.base;
- U32 const current = (U32)(ip-base);
- U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
+ U32 const curr = (U32)(ip-base);
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);
U32* const bt = ms->chainTable;
U32 const btLog = cParams->chainLog - 1;
U32 const btMask = (1 << btLog) - 1;
- U32 const btLow = (btMask >= current) ? 0 : current - btMask;
+ U32 const btLow = (btMask >= curr) ? 0 : curr - btMask;
U32 const unsortLimit = MAX(btLow, windowLow);
U32* nextCandidate = bt + 2*(matchIndex&btMask);
@@ -256,8 +256,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
U32 nbCandidates = nbCompares;
U32 previousCandidate = 0;
- DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current);
+ DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", curr);
assert(ip <= iend-8); /* required for h calculation */
+ assert(dictMode != ZSTD_dedicatedDictSearch);
/* reach end of unsorted candidates list */
while ( (matchIndex > unsortLimit)
@@ -299,14 +300,14 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
const U32 dictLimit = ms->window.dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current + 8 + 1;
+ U32* smallerPtr = bt + 2*(curr&btMask);
+ U32* largerPtr = bt + 2*(curr&btMask) + 1;
+ U32 matchEndIdx = curr + 8 + 1;
U32 dummy32; /* to be nullified at the end */
size_t bestLength = 0;
matchIndex = hashTable[h];
- hashTable[h] = current; /* Update Hash Table */
+ hashTable[h] = curr; /* Update Hash Table */
while (nbCompares-- && (matchIndex > windowLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
@@ -326,8 +327,8 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
if (matchLength > bestLength) {
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
- if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
+ if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
+ bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
if (dictMode == ZSTD_dictMatchState) {
nbCompares = 0; /* in addition to avoiding checking any
@@ -363,12 +364,12 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
mls, dictMode);
}
- assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */
+ assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
if (bestLength >= MINMATCH) {
- U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
- current, (U32)bestLength, (U32)*offsetPtr, mIndex);
+ curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
}
return bestLength;
}
@@ -437,6 +438,220 @@ static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
}
}
+/***********************************
+* Dedicated dict search
+***********************************/
+
+void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip)
+{
+ const BYTE* const base = ms->window.base;
+ U32 const target = (U32)(ip - base);
+ U32* const hashTable = ms->hashTable;
+ U32* const chainTable = ms->chainTable;
+ U32 const chainSize = 1 << ms->cParams.chainLog;
+ U32 idx = ms->nextToUpdate;
+ U32 const minChain = chainSize < target ? target - chainSize : idx;
+ U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG;
+ U32 const cacheSize = bucketSize - 1;
+ U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize;
+ U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts;
+
+ /* We know the hashtable is oversized by a factor of `bucketSize`.
+ * We are going to temporarily pretend `bucketSize == 1`, keeping only a
+ * single entry. We will use the rest of the space to construct a temporary
+ * chaintable.
+ */
+ U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;
+ U32* const tmpHashTable = hashTable;
+ U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog);
+ U32 const tmpChainSize = ((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;
+ U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx;
+ U32 hashIdx;
+
+ assert(ms->cParams.chainLog <= 24);
+ assert(ms->cParams.hashLog > ms->cParams.chainLog);
+ assert(idx != 0);
+ assert(tmpMinChain <= minChain);
+
+ /* fill conventional hash table and conventional chain table */
+ for ( ; idx < target; idx++) {
+ U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch);
+ if (idx >= tmpMinChain) {
+ tmpChainTable[idx - tmpMinChain] = hashTable[h];
+ }
+ tmpHashTable[h] = idx;
+ }
+
+ /* sort chains into ddss chain table */
+ {
+ U32 chainPos = 0;
+ for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) {
+ U32 count;
+ U32 countBeyondMinChain = 0;
+ U32 i = tmpHashTable[hashIdx];
+ for (count = 0; i >= tmpMinChain && count < cacheSize; count++) {
+ /* skip through the chain to the first position that won't be
+ * in the hash cache bucket */
+ if (i < minChain) {
+ countBeyondMinChain++;
+ }
+ i = tmpChainTable[i - tmpMinChain];
+ }
+ if (count == cacheSize) {
+ for (count = 0; count < chainLimit;) {
+ if (i < minChain) {
+ if (!i || ++countBeyondMinChain > cacheSize) {
+ /* only allow pulling `cacheSize` number of entries
+ * into the cache or chainTable beyond `minChain`,
+ * to replace the entries pulled out of the
+ * chainTable into the cache. This lets us reach
+ * back further without increasing the total number
+ * of entries in the chainTable, guaranteeing the
+ * DDSS chain table will fit into the space
+ * allocated for the regular one. */
+ break;
+ }
+ }
+ chainTable[chainPos++] = i;
+ count++;
+ if (i < tmpMinChain) {
+ break;
+ }
+ i = tmpChainTable[i - tmpMinChain];
+ }
+ } else {
+ count = 0;
+ }
+ if (count) {
+ tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count;
+ } else {
+ tmpHashTable[hashIdx] = 0;
+ }
+ }
+ assert(chainPos <= chainSize); /* I believe this is guaranteed... */
+ }
+
+ /* move chain pointers into the last entry of each hash bucket */
+ for (hashIdx = (1 << hashLog); hashIdx; ) {
+ U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG;
+ U32 const chainPackedPointer = tmpHashTable[hashIdx];
+ U32 i;
+ for (i = 0; i < cacheSize; i++) {
+ hashTable[bucketIdx + i] = 0;
+ }
+ hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer;
+ }
+
+ /* fill the buckets of the hash table */
+ for (idx = ms->nextToUpdate; idx < target; idx++) {
+ U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch)
+ << ZSTD_LAZY_DDSS_BUCKET_LOG;
+ U32 i;
+ /* Shift hash cache down 1. */
+ for (i = cacheSize - 1; i; i--)
+ hashTable[h + i] = hashTable[h + i - 1];
+ hashTable[h] = idx;
+ }
+
+ ms->nextToUpdate = target;
+}
+
+/* Returns the longest match length found in the dedicated dict search structure.
+ * If none are longer than the argument ml, then ml will be returned.
+ */
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts,
+ const ZSTD_matchState_t* const dms,
+ const BYTE* const ip, const BYTE* const iLimit,
+ const BYTE* const prefixStart, const U32 curr,
+ const U32 dictLimit, const size_t ddsIdx) {
+ const U32 ddsLowestIndex = dms->window.dictLimit;
+ const BYTE* const ddsBase = dms->window.base;
+ const BYTE* const ddsEnd = dms->window.nextSrc;
+ const U32 ddsSize = (U32)(ddsEnd - ddsBase);
+ const U32 ddsIndexDelta = dictLimit - ddsSize;
+ const U32 bucketSize = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG);
+ const U32 bucketLimit = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1;
+ U32 ddsAttempt;
+ U32 matchIndex;
+
+ for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) {
+ PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]);
+ }
+
+ {
+ U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];
+ U32 const chainIndex = chainPackedPointer >> 8;
+
+ PREFETCH_L1(&dms->chainTable[chainIndex]);
+ }
+
+ for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) {
+ size_t currentMl=0;
+ const BYTE* match;
+ matchIndex = dms->hashTable[ddsIdx + ddsAttempt];
+ match = ddsBase + matchIndex;
+
+ if (!matchIndex) {
+ return ml;
+ }
+
+ /* guaranteed by table construction */
+ (void)ddsLowestIndex;
+ assert(matchIndex >= ddsLowestIndex);
+ assert(match+4 <= ddsEnd);
+ if (MEM_read32(match) == MEM_read32(ip)) {
+ /* assumption : matchIndex <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;
+ }
+
+ /* save best solution */
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) {
+ /* best possible, avoids read overflow on next attempt */
+ return ml;
+ }
+ }
+ }
+
+ {
+ U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];
+ U32 chainIndex = chainPackedPointer >> 8;
+ U32 const chainLength = chainPackedPointer & 0xFF;
+ U32 const chainAttempts = nbAttempts - ddsAttempt;
+ U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts;
+ U32 chainAttempt;
+
+ for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) {
+ PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]);
+ }
+
+ for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) {
+ size_t currentMl=0;
+ const BYTE* match;
+ matchIndex = dms->chainTable[chainIndex];
+ match = ddsBase + matchIndex;
+
+ /* guaranteed by table construction */
+ assert(matchIndex >= ddsLowestIndex);
+ assert(match+4 <= ddsEnd);
+ if (MEM_read32(match) == MEM_read32(ip)) {
+ /* assumption : matchIndex <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;
+ }
+
+ /* save best solution */
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
+ }
+ }
+ }
+ return ml;
+}
/* *********************************
@@ -446,7 +661,7 @@ static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
/* Update chains up to ip (excluded)
Assumption : always within prefix (i.e. not within extDict) */
-static U32 ZSTD_insertAndFindFirstIndex_internal(
+FORCE_INLINE_TEMPLATE U32 ZSTD_insertAndFindFirstIndex_internal(
ZSTD_matchState_t* ms,
const ZSTD_compressionParameters* const cParams,
const BYTE* ip, U32 const mls)
@@ -475,7 +690,6 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch);
}
-
/* inlining is important to hardwire a hot branch (template emulation) */
FORCE_INLINE_TEMPLATE
size_t ZSTD_HcFindBestMatch_generic (
@@ -493,20 +707,33 @@ size_t ZSTD_HcFindBestMatch_generic (
const U32 dictLimit = ms->window.dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
- const U32 current = (U32)(ip-base);
+ const U32 curr = (U32)(ip-base);
const U32 maxDistance = 1U << cParams->windowLog;
const U32 lowestValid = ms->window.lowLimit;
- const U32 withinMaxDistance = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid;
+ const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
const U32 isDictionary = (ms->loadedDictEnd != 0);
const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;
- const U32 minChain = current > chainSize ? current - chainSize : 0;
+ const U32 minChain = curr > chainSize ? curr - chainSize : 0;
U32 nbAttempts = 1U << cParams->searchLog;
size_t ml=4-1;
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch
+ ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0;
+ const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch
+ ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0;
+
+ U32 matchIndex;
+
+ if (dictMode == ZSTD_dedicatedDictSearch) {
+ const U32* entry = &dms->hashTable[ddsIdx];
+ PREFETCH_L1(entry);
+ }
+
/* HC4 match finder */
- U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls);
+ matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls);
- for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) {
+ for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) {
size_t currentMl=0;
if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {
const BYTE* const match = base + matchIndex;
@@ -523,7 +750,7 @@ size_t ZSTD_HcFindBestMatch_generic (
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
+ *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
@@ -531,8 +758,10 @@ size_t ZSTD_HcFindBestMatch_generic (
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
}
- if (dictMode == ZSTD_dictMatchState) {
- const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ if (dictMode == ZSTD_dedicatedDictSearch) {
+ ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms,
+ ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
+ } else if (dictMode == ZSTD_dictMatchState) {
const U32* const dmsChainTable = dms->chainTable;
const U32 dmsChainSize = (1 << dms->cParams.chainLog);
const U32 dmsChainMask = dmsChainSize - 1;
@@ -545,7 +774,7 @@ size_t ZSTD_HcFindBestMatch_generic (
matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)];
- for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {
+ for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {
size_t currentMl=0;
const BYTE* const match = dmsBase + matchIndex;
assert(match+4 <= dmsEnd);
@@ -555,11 +784,12 @@ size_t ZSTD_HcFindBestMatch_generic (
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
+ *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
if (matchIndex <= dmsMinChain) break;
+
matchIndex = dmsChainTable[matchIndex & dmsChainMask];
}
}
@@ -600,6 +830,22 @@ static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS (
}
+static size_t ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ switch(ms->cParams.minMatch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dedicatedDictSearch);
+ case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dedicatedDictSearch);
+ case 7 :
+ case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dedicatedDictSearch);
+ }
+}
+
+
FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* const iLimit,
@@ -615,11 +861,658 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
}
}
+/* *********************************
+* (SIMD) Row-based matchfinder
+***********************************/
+/* Constants for row-based hash */
+#define ZSTD_ROW_HASH_TAG_OFFSET 1 /* byte offset of hashes in the match state's tagTable from the beginning of a row */
+#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */
+#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1)
+
+#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1)
+
+typedef U32 ZSTD_VecMask; /* Clarifies when we are interacting with a U32 representing a mask of matches */
+
+#if !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) /* SIMD SSE version */
+
+#include <emmintrin.h>
+typedef __m128i ZSTD_Vec128;
+
+/* Returns a 128-bit container with 128-bits from src */
+static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
+ return _mm_loadu_si128((ZSTD_Vec128 const*)src);
+}
+
+/* Returns a ZSTD_Vec128 with the byte "val" packed 16 times */
+static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
+ return _mm_set1_epi8((char)val);
+}
+
+/* Do byte-by-byte comparison result of x and y. Then collapse 128-bit resultant mask
+ * into a 32-bit mask that is the MSB of each byte.
+ * */
+static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
+ return (ZSTD_VecMask)_mm_movemask_epi8(_mm_cmpeq_epi8(x, y));
+}
+
+typedef struct {
+ __m128i fst;
+ __m128i snd;
+} ZSTD_Vec256;
+
+static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) {
+ ZSTD_Vec256 v;
+ v.fst = ZSTD_Vec128_read(ptr);
+ v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1);
+ return v;
+}
+
+static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
+ ZSTD_Vec256 v;
+ v.fst = ZSTD_Vec128_set8(val);
+ v.snd = ZSTD_Vec128_set8(val);
+ return v;
+}
+
+static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
+ ZSTD_VecMask fstMask;
+ ZSTD_VecMask sndMask;
+ fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst);
+ sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd);
+ return fstMask | (sndMask << 16);
+}
+
+#elif !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) /* SIMD ARM NEON Version */
+
+#include <arm_neon.h>
+typedef uint8x16_t ZSTD_Vec128;
+
+static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
+ return vld1q_u8((const BYTE* const)src);
+}
+
+static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
+ return vdupq_n_u8(val);
+}
+
+/* Mimics '_mm_movemask_epi8()' from SSE */
+static U32 ZSTD_vmovmaskq_u8(ZSTD_Vec128 val) {
+ /* Shift out everything but the MSB bits in each byte */
+ uint16x8_t highBits = vreinterpretq_u16_u8(vshrq_n_u8(val, 7));
+ /* Merge the even lanes together with vsra (right shift and add) */
+ uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(highBits, highBits, 7));
+ uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
+ uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
+ /* Extract the low 8 bits from each lane, merge */
+ return vgetq_lane_u8(paired64, 0) | ((U32)vgetq_lane_u8(paired64, 8) << 8);
+}
+
+static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
+ return (ZSTD_VecMask)ZSTD_vmovmaskq_u8(vceqq_u8(x, y));
+}
+
+typedef struct {
+ uint8x16_t fst;
+ uint8x16_t snd;
+} ZSTD_Vec256;
+
+static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) {
+ ZSTD_Vec256 v;
+ v.fst = ZSTD_Vec128_read(ptr);
+ v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1);
+ return v;
+}
+
+static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
+ ZSTD_Vec256 v;
+ v.fst = ZSTD_Vec128_set8(val);
+ v.snd = ZSTD_Vec128_set8(val);
+ return v;
+}
+
+static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
+ ZSTD_VecMask fstMask;
+ ZSTD_VecMask sndMask;
+ fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst);
+ sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd);
+ return fstMask | (sndMask << 16);
+}
+
+#else /* Scalar fallback version */
+
+#define VEC128_NB_SIZE_T (16 / sizeof(size_t))
+typedef struct {
+ size_t vec[VEC128_NB_SIZE_T];
+} ZSTD_Vec128;
+
+static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
+ ZSTD_Vec128 ret;
+ ZSTD_memcpy(ret.vec, src, VEC128_NB_SIZE_T*sizeof(size_t));
+ return ret;
+}
+
+static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
+ ZSTD_Vec128 ret = { {0} };
+ int startBit = sizeof(size_t) * 8 - 8;
+ for (;startBit >= 0; startBit -= 8) {
+ unsigned j = 0;
+ for (;j < VEC128_NB_SIZE_T; ++j) {
+ ret.vec[j] |= ((size_t)val << startBit);
+ }
+ }
+ return ret;
+}
+
+/* Compare x to y, byte by byte, generating a "matches" bitfield */
+static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
+ ZSTD_VecMask res = 0;
+ unsigned i = 0;
+ unsigned l = 0;
+ for (; i < VEC128_NB_SIZE_T; ++i) {
+ const size_t cmp1 = x.vec[i];
+ const size_t cmp2 = y.vec[i];
+ unsigned j = 0;
+ for (; j < sizeof(size_t); ++j, ++l) {
+ if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) {
+ res |= ((U32)1 << (j+i*sizeof(size_t)));
+ }
+ }
+ }
+ return res;
+}
+
+#define VEC256_NB_SIZE_T 2*VEC128_NB_SIZE_T
+typedef struct {
+ size_t vec[VEC256_NB_SIZE_T];
+} ZSTD_Vec256;
+
+static ZSTD_Vec256 ZSTD_Vec256_read(const void* const src) {
+ ZSTD_Vec256 ret;
+ ZSTD_memcpy(ret.vec, src, VEC256_NB_SIZE_T*sizeof(size_t));
+ return ret;
+}
+
+static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
+ ZSTD_Vec256 ret = { {0} };
+ int startBit = sizeof(size_t) * 8 - 8;
+ for (;startBit >= 0; startBit -= 8) {
+ unsigned j = 0;
+ for (;j < VEC256_NB_SIZE_T; ++j) {
+ ret.vec[j] |= ((size_t)val << startBit);
+ }
+ }
+ return ret;
+}
+
+/* Compare x to y, byte by byte, generating a "matches" bitfield */
+static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
+ ZSTD_VecMask res = 0;
+ unsigned i = 0;
+ unsigned l = 0;
+ for (; i < VEC256_NB_SIZE_T; ++i) {
+ const size_t cmp1 = x.vec[i];
+ const size_t cmp2 = y.vec[i];
+ unsigned j = 0;
+ for (; j < sizeof(size_t); ++j, ++l) {
+ if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) {
+ res |= ((U32)1 << (j+i*sizeof(size_t)));
+ }
+ }
+ }
+ return res;
+}
+
+#endif /* !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) */
+
+/* ZSTD_VecMask_next():
+ * Starting from the LSB, returns the idx of the next non-zero bit.
+ * Basically counting the nb of trailing zeroes.
+ */
+static U32 ZSTD_VecMask_next(ZSTD_VecMask val) {
+# if defined(_MSC_VER) /* Visual */
+ unsigned long r=0;
+ return _BitScanForward(&r, val) ? (U32)r : 0;
+# elif defined(__GNUC__) && (__GNUC__ >= 3)
+ return (U32)__builtin_ctz(val);
+# else
+ /* Software ctz version: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
+ static const U32 multiplyDeBruijnBitPosition[32] =
+ {
+ 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+ };
+ return multiplyDeBruijnBitPosition[((U32)((val & -(int)val) * 0x077CB531U)) >> 27];
+
+# endif
+}
+
+/* ZSTD_VecMask_rotateRight():
+ * Rotates a bitfield to the right by "rotation" bits.
+ * If the rotation is greater than totalBits, the returned mask is 0.
+ */
+FORCE_INLINE_TEMPLATE ZSTD_VecMask
+ZSTD_VecMask_rotateRight(ZSTD_VecMask mask, U32 const rotation, U32 const totalBits) {
+ if (rotation == 0)
+ return mask;
+ switch (totalBits) {
+ default:
+ assert(0);
+ case 16:
+ return (mask >> rotation) | (U16)(mask << (16 - rotation));
+ case 32:
+ return (mask >> rotation) | (U32)(mask << (32 - rotation));
+ }
+}
+
+/* ZSTD_row_nextIndex():
+ * Returns the next index to insert at within a tagTable row, and updates the "head"
+ * value to reflect the update. Essentially cycles backwards from [0, {entries per row})
+ */
+FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextIndex(BYTE* const tagRow, U32 const rowMask) {
+ U32 const next = (*tagRow - 1) & rowMask;
+ *tagRow = (BYTE)next;
+ return next;
+}
+
+/* ZSTD_isAligned():
+ * Checks that a pointer is aligned to "align" bytes which must be a power of 2.
+ */
+MEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) {
+ assert((align & (align - 1)) == 0);
+ return (((size_t)ptr) & (align - 1)) == 0;
+}
+
+/* ZSTD_row_prefetch():
+ * Performs prefetching for the hashTable and tagTable at a given row.
+ */
+FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, U16 const* tagTable, U32 const relRow, U32 const rowLog) {
+ PREFETCH_L1(hashTable + relRow);
+ if (rowLog == 5) {
+ PREFETCH_L1(hashTable + relRow + 16);
+ }
+ PREFETCH_L1(tagTable + relRow);
+ assert(rowLog == 4 || rowLog == 5);
+ assert(ZSTD_isAligned(hashTable + relRow, 64)); /* prefetched hash row always 64-byte aligned */
+ assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on a multiple of 32 or 64 bytes */
+}
+
+/* ZSTD_row_fillHashCache():
+ * Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries,
+ * but not beyond iLimit.
+ */
+static void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base,
+ U32 const rowLog, U32 const mls,
+ U32 idx, const BYTE* const iLimit)
+{
+ U32 const* const hashTable = ms->hashTable;
+ U16 const* const tagTable = ms->tagTable;
+ U32 const hashLog = ms->rowHashLog;
+ U32 const maxElemsToPrefetch = (base + idx) > iLimit ? 0 : (U32)(iLimit - (base + idx) + 1);
+ U32 const lim = idx + MIN(ZSTD_ROW_HASH_CACHE_SIZE, maxElemsToPrefetch);
+
+ for (; idx < lim; ++idx) {
+ U32 const hash = (U32)ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
+ U32 const row = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
+ ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);
+ ms->hashCache[idx & ZSTD_ROW_HASH_CACHE_MASK] = hash;
+ }
+
+ DEBUGLOG(6, "ZSTD_row_fillHashCache(): [%u %u %u %u %u %u %u %u]", ms->hashCache[0], ms->hashCache[1],
+ ms->hashCache[2], ms->hashCache[3], ms->hashCache[4],
+ ms->hashCache[5], ms->hashCache[6], ms->hashCache[7]);
+}
+
+/* ZSTD_row_nextCachedHash():
+ * Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at
+ * base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable.
+ */
+FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable,
+ U16 const* tagTable, BYTE const* base,
+ U32 idx, U32 const hashLog,
+ U32 const rowLog, U32 const mls)
+{
+ U32 const newHash = (U32)ZSTD_hashPtr(base+idx+ZSTD_ROW_HASH_CACHE_SIZE, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
+ U32 const row = (newHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
+ ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);
+ { U32 const hash = cache[idx & ZSTD_ROW_HASH_CACHE_MASK];
+ cache[idx & ZSTD_ROW_HASH_CACHE_MASK] = newHash;
+ return hash;
+ }
+}
+
+/* ZSTD_row_update_internal():
+ * Inserts the byte at ip into the appropriate position in the hash table.
+ * Determines the relative row, and the position within the {16, 32} entry row to insert at.
+ */
+FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip,
+ U32 const mls, U32 const rowLog,
+ U32 const rowMask, U32 const useCache)
+{
+ U32* const hashTable = ms->hashTable;
+ U16* const tagTable = ms->tagTable;
+ U32 const hashLog = ms->rowHashLog;
+ const BYTE* const base = ms->window.base;
+ const U32 target = (U32)(ip - base);
+ U32 idx = ms->nextToUpdate;
+
+ DEBUGLOG(6, "ZSTD_row_update_internal(): nextToUpdate=%u, current=%u", idx, target);
+ for (; idx < target; ++idx) {
+ U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, idx, hashLog, rowLog, mls)
+ : (U32)ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
+ U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
+ U32* const row = hashTable + relRow;
+ BYTE* tagRow = (BYTE*)(tagTable + relRow); /* Though tagTable is laid out as a table of U16, each tag is only 1 byte.
+ Explicit cast allows us to get exact desired position within each row */
+ U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);
+
+ assert(hash == ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls));
+ ((BYTE*)tagRow)[pos + ZSTD_ROW_HASH_TAG_OFFSET] = hash & ZSTD_ROW_HASH_TAG_MASK;
+ row[pos] = idx;
+ }
+ ms->nextToUpdate = target;
+}
+
+/* ZSTD_row_update():
+ * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary
+ * processing.
+ */
+void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) {
+ const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
+ const U32 rowMask = (1u << rowLog) - 1;
+ const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */);
+
+ DEBUGLOG(5, "ZSTD_row_update(), rowLog=%u", rowLog);
+ ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* dont use cache */);
+}
+
+/* Returns a ZSTD_VecMask (U32) that has the nth bit set to 1 if the newly-computed "tag" matches
+ * the hash at the nth position in a row of the tagTable.
+ */
+FORCE_INLINE_TEMPLATE
+ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries) {
+ ZSTD_VecMask matches = 0;
+ if (rowEntries == 16) {
+ ZSTD_Vec128 hashes = ZSTD_Vec128_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET);
+ ZSTD_Vec128 expandedTags = ZSTD_Vec128_set8(tag);
+ matches = ZSTD_Vec128_cmpMask8(hashes, expandedTags);
+ } else if (rowEntries == 32) {
+ ZSTD_Vec256 hashes = ZSTD_Vec256_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET);
+ ZSTD_Vec256 expandedTags = ZSTD_Vec256_set8(tag);
+ matches = ZSTD_Vec256_cmpMask8(hashes, expandedTags);
+ } else {
+ assert(0);
+ }
+ /* Each row is a circular buffer beginning at the value of "head". So we must rotate the "matches" bitfield
+ to match up with the actual layout of the entries within the hashTable */
+ return ZSTD_VecMask_rotateRight(matches, head, rowEntries);
+}
+
+/* The high-level approach of the SIMD row based match finder is as follows:
+ * - Figure out where to insert the new entry:
+ * - Generate a hash from a byte along with an additional 1-byte "short hash". The additional byte is our "tag"
+ * - The hashTable is effectively split into groups or "rows" of 16 or 32 entries of U32, and the hash determines
+ * which row to insert into.
+ * - Determine the correct position within the row to insert the entry into. Each row of 16 or 32 can
+ * be considered as a circular buffer with a "head" index that resides in the tagTable.
+ * - Also insert the "tag" into the equivalent row and position in the tagTable.
+ * - Note: The tagTable has 17 or 33 1-byte entries per row, due to 16 or 32 tags, and 1 "head" entry.
+ * The 17 or 33 entry rows are spaced out to occur every 32 or 64 bytes, respectively,
+ * for alignment/performance reasons, leaving some bytes unused.
+ * - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte "short hash" and
+ * generate a bitfield that we can cycle through to check the collisions in the hash table.
+ * - Pick the longest match.
+ */
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_RowFindBestMatch_generic (
+ ZSTD_matchState_t* ms,
+ const BYTE* const ip, const BYTE* const iLimit,
+ size_t* offsetPtr,
+ const U32 mls, const ZSTD_dictMode_e dictMode,
+ const U32 rowLog)
+{
+ U32* const hashTable = ms->hashTable;
+ U16* const tagTable = ms->tagTable;
+ U32* const hashCache = ms->hashCache;
+ const U32 hashLog = ms->rowHashLog;
+ const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const dictBase = ms->window.dictBase;
+ const U32 dictLimit = ms->window.dictLimit;
+ const BYTE* const prefixStart = base + dictLimit;
+ const BYTE* const dictEnd = dictBase + dictLimit;
+ const U32 curr = (U32)(ip-base);
+ const U32 maxDistance = 1U << cParams->windowLog;
+ const U32 lowestValid = ms->window.lowLimit;
+ const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
+ const U32 isDictionary = (ms->loadedDictEnd != 0);
+ const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;
+ const U32 rowEntries = (1U << rowLog);
+ const U32 rowMask = rowEntries - 1;
+ const U32 cappedSearchLog = MIN(cParams->searchLog, rowLog); /* nb of searches is capped at nb entries per row */
+ U32 nbAttempts = 1U << cappedSearchLog;
+ size_t ml=4-1;
+
+ /* DMS/DDS variables that may be referenced laster */
+ const ZSTD_matchState_t* const dms = ms->dictMatchState;
+ size_t ddsIdx;
+ U32 ddsExtraAttempts; /* cctx hash tables are limited in searches, but allow extra searches into DDS */
+ U32 dmsTag;
+ U32* dmsRow;
+ BYTE* dmsTagRow;
+
+ if (dictMode == ZSTD_dedicatedDictSearch) {
+ const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;
+ { /* Prefetch DDS hashtable entry */
+ ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG;
+ PREFETCH_L1(&dms->hashTable[ddsIdx]);
+ }
+ ddsExtraAttempts = cParams->searchLog > rowLog ? 1U << (cParams->searchLog - rowLog) : 0;
+ }
+
+ if (dictMode == ZSTD_dictMatchState) {
+ /* Prefetch DMS rows */
+ U32* const dmsHashTable = dms->hashTable;
+ U16* const dmsTagTable = dms->tagTable;
+ U32 const dmsHash = (U32)ZSTD_hashPtr(ip, dms->rowHashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
+ U32 const dmsRelRow = (dmsHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
+ dmsTag = dmsHash & ZSTD_ROW_HASH_TAG_MASK;
+ dmsTagRow = (BYTE*)(dmsTagTable + dmsRelRow);
+ dmsRow = dmsHashTable + dmsRelRow;
+ ZSTD_row_prefetch(dmsHashTable, dmsTagTable, dmsRelRow, rowLog);
+ }
+
+ /* Update the hashTable and tagTable up to (but not including) ip */
+ ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 1 /* useCache */);
+ { /* Get the hash for ip, compute the appropriate row */
+ U32 const hash = ZSTD_row_nextCachedHash(hashCache, hashTable, tagTable, base, curr, hashLog, rowLog, mls);
+ U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
+ U32 const tag = hash & ZSTD_ROW_HASH_TAG_MASK;
+ U32* const row = hashTable + relRow;
+ BYTE* tagRow = (BYTE*)(tagTable + relRow);
+ U32 const head = *tagRow & rowMask;
+ U32 matchBuffer[32 /* maximum nb entries per row */];
+ size_t numMatches = 0;
+ size_t currMatch = 0;
+ ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, head, rowEntries);
+
+ /* Cycle through the matches and prefetch */
+ for (; (matches > 0) && (nbAttempts > 0); --nbAttempts, matches &= (matches - 1)) {
+ U32 const matchPos = (head + ZSTD_VecMask_next(matches)) & rowMask;
+ U32 const matchIndex = row[matchPos];
+ assert(numMatches < rowEntries);
+ if (matchIndex < lowLimit)
+ break;
+ if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {
+ PREFETCH_L1(base + matchIndex);
+ } else {
+ PREFETCH_L1(dictBase + matchIndex);
+ }
+ matchBuffer[numMatches++] = matchIndex;
+ }
+
+ /* Speed opt: insert current byte into hashtable too. This allows us to avoid one iteration of the loop
+ in ZSTD_row_update_internal() at the next search. */
+ {
+ U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);
+ tagRow[pos + ZSTD_ROW_HASH_TAG_OFFSET] = (BYTE)tag;
+ row[pos] = ms->nextToUpdate++;
+ }
+
+ /* Return the longest match */
+ for (; currMatch < numMatches; ++currMatch) {
+ U32 const matchIndex = matchBuffer[currMatch];
+ size_t currentMl=0;
+ assert(matchIndex < curr);
+ assert(matchIndex >= lowLimit);
+
+ if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {
+ const BYTE* const match = base + matchIndex;
+ assert(matchIndex >= dictLimit); /* ensures this is true if dictMode != ZSTD_extDict */
+ if (match[ml] == ip[ml]) /* potentially better */
+ currentMl = ZSTD_count(ip, match, iLimit);
+ } else {
+ const BYTE* const match = dictBase + matchIndex;
+ assert(match+4 <= dictEnd);
+ if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
+ }
+
+ /* Save best solution */
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
+ }
+ }
+ }
+
+ if (dictMode == ZSTD_dedicatedDictSearch) {
+ ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms,
+ ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
+ } else if (dictMode == ZSTD_dictMatchState) {
+ /* TODO: Measure and potentially add prefetching to DMS */
+ const U32 dmsLowestIndex = dms->window.dictLimit;
+ const BYTE* const dmsBase = dms->window.base;
+ const BYTE* const dmsEnd = dms->window.nextSrc;
+ const U32 dmsSize = (U32)(dmsEnd - dmsBase);
+ const U32 dmsIndexDelta = dictLimit - dmsSize;
+
+ { U32 const head = *dmsTagRow & rowMask;
+ U32 matchBuffer[32 /* maximum nb row entries */];
+ size_t numMatches = 0;
+ size_t currMatch = 0;
+ ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, head, rowEntries);
+
+ for (; (matches > 0) && (nbAttempts > 0); --nbAttempts, matches &= (matches - 1)) {
+ U32 const matchPos = (head + ZSTD_VecMask_next(matches)) & rowMask;
+ U32 const matchIndex = dmsRow[matchPos];
+ if (matchIndex < dmsLowestIndex)
+ break;
+ PREFETCH_L1(dmsBase + matchIndex);
+ matchBuffer[numMatches++] = matchIndex;
+ }
+
+ /* Return the longest match */
+ for (; currMatch < numMatches; ++currMatch) {
+ U32 const matchIndex = matchBuffer[currMatch];
+ size_t currentMl=0;
+ assert(matchIndex >= dmsLowestIndex);
+ assert(matchIndex < curr);
+
+ { const BYTE* const match = dmsBase + matchIndex;
+ assert(match+4 <= dmsEnd);
+ if (MEM_read32(match) == MEM_read32(ip))
+ currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;
+ }
+
+ if (currentMl > ml) {
+ ml = currentMl;
+ *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
+ if (ip+currentMl == iLimit) break;
+ }
+ }
+ }
+ }
+ return ml;
+}
+
+/* Inlining is important to hardwire a hot branch (template emulation) */
+FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectMLS (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ const ZSTD_dictMode_e dictMode, size_t* offsetPtr, const U32 rowLog)
+{
+ switch(ms->cParams.minMatch)
+ {
+ default : /* includes case 3 */
+ case 4 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, dictMode, rowLog);
+ case 5 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, dictMode, rowLog);
+ case 7 :
+ case 6 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, dictMode, rowLog);
+ }
+}
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectRowLog (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
+ switch(cappedSearchLog)
+ {
+ default :
+ case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 4);
+ case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 5);
+ }
+}
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dictMatchState_selectRowLog(
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
+ switch(cappedSearchLog)
+ {
+ default :
+ case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 4);
+ case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 5);
+ }
+}
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog(
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
+ switch(cappedSearchLog)
+ {
+ default :
+ case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 4);
+ case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 5);
+ }
+}
+
+FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_extDict_selectRowLog (
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* const iLimit,
+ size_t* offsetPtr)
+{
+ const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
+ switch(cappedSearchLog)
+ {
+ default :
+ case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 4);
+ case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 5);
+ }
+}
+
/* *******************************
* Common parser - lazy strategy
*********************************/
-typedef enum { search_hashChain, search_binaryTree } searchMethod_e;
+typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e;
FORCE_INLINE_TEMPLATE size_t
ZSTD_compressBlock_lazy_generic(
@@ -633,53 +1526,85 @@ ZSTD_compressBlock_lazy_generic(
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
+ const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
const BYTE* const base = ms->window.base;
const U32 prefixLowestIndex = ms->window.dictLimit;
const BYTE* const prefixLowest = base + prefixLowestIndex;
+ const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
typedef size_t (*searchMax_f)(
ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
- searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ?
- (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS
- : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) :
- (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_selectMLS
- : ZSTD_HcFindBestMatch_selectMLS);
+
+ /**
+ * This table is indexed first by the four ZSTD_dictMode_e values, and then
+ * by the two searchMethod_e values. NULLs are placed for configurations
+ * that should never occur (extDict modes go to the other implementation
+ * below and there is no DDSS for binary tree search yet).
+ */
+ const searchMax_f searchFuncs[4][3] = {
+ {
+ ZSTD_HcFindBestMatch_selectMLS,
+ ZSTD_BtFindBestMatch_selectMLS,
+ ZSTD_RowFindBestMatch_selectRowLog
+ },
+ {
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ZSTD_HcFindBestMatch_dictMatchState_selectMLS,
+ ZSTD_BtFindBestMatch_dictMatchState_selectMLS,
+ ZSTD_RowFindBestMatch_dictMatchState_selectRowLog
+ },
+ {
+ ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS,
+ NULL,
+ ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog
+ }
+ };
+
+ searchMax_f const searchMax = searchFuncs[dictMode][(int)searchMethod];
U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
+ const int isDMS = dictMode == ZSTD_dictMatchState;
+ const int isDDS = dictMode == ZSTD_dedicatedDictSearch;
+ const int isDxS = isDMS || isDDS;
const ZSTD_matchState_t* const dms = ms->dictMatchState;
- const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ?
- dms->window.dictLimit : 0;
- const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
- dms->window.base : NULL;
- const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ?
- dictBase + dictLowestIndex : NULL;
- const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
- dms->window.nextSrc : NULL;
- const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
+ const U32 dictLowestIndex = isDxS ? dms->window.dictLimit : 0;
+ const BYTE* const dictBase = isDxS ? dms->window.base : NULL;
+ const BYTE* const dictLowest = isDxS ? dictBase + dictLowestIndex : NULL;
+ const BYTE* const dictEnd = isDxS ? dms->window.nextSrc : NULL;
+ const U32 dictIndexDelta = isDxS ?
prefixLowestIndex - (U32)(dictEnd - dictBase) :
0;
const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest));
- DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u)", (U32)dictMode);
+ assert(searchMax != NULL);
- /* init */
+ DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u) (searchFunc=%u)", (U32)dictMode, (U32)searchMethod);
ip += (dictAndPrefixLength == 0);
if (dictMode == ZSTD_noDict) {
- U32 const current = (U32)(ip - base);
- U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, ms->cParams.windowLog);
- U32 const maxRep = current - windowLow;
+ U32 const curr = (U32)(ip - base);
+ U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog);
+ U32 const maxRep = curr - windowLow;
if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0;
if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0;
}
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
/* dictMatchState repCode checks don't currently handle repCode == 0
* disabling. */
assert(offset_1 <= dictAndPrefixLength);
assert(offset_2 <= dictAndPrefixLength);
}
+ if (searchMethod == search_rowHash) {
+ ZSTD_row_fillHashCache(ms, base, rowLog,
+ MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */),
+ ms->nextToUpdate, ilimit);
+ }
+
/* Match Loop */
#if defined(__GNUC__) && defined(__x86_64__)
/* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the
@@ -693,9 +1618,9 @@ ZSTD_compressBlock_lazy_generic(
const BYTE* start=ip+1;
/* check repCode */
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
const U32 repIndex = (U32)(ip - base) + 1 - offset_1;
- const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
+ const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch)
&& repIndex < prefixLowestIndex) ?
dictBase + (repIndex - dictIndexDelta) :
base + repIndex;
@@ -736,7 +1661,7 @@ ZSTD_compressBlock_lazy_generic(
if ((mlRep >= 4) && (gain2 > gain1))
matchLength = mlRep, offset = 0, start = ip;
}
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
const U32 repIndex = (U32)(ip - base) - offset_1;
const BYTE* repMatch = repIndex < prefixLowestIndex ?
dictBase + (repIndex - dictIndexDelta) :
@@ -771,7 +1696,7 @@ ZSTD_compressBlock_lazy_generic(
if ((mlRep >= 4) && (gain2 > gain1))
matchLength = mlRep, offset = 0, start = ip;
}
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
const U32 repIndex = (U32)(ip - base) - offset_1;
const BYTE* repMatch = repIndex < prefixLowestIndex ?
dictBase + (repIndex - dictIndexDelta) :
@@ -809,7 +1734,7 @@ ZSTD_compressBlock_lazy_generic(
&& (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
{ start--; matchLength++; }
}
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;
const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;
@@ -825,12 +1750,11 @@ _storeSequence:
}
/* check immediate repcode */
- if (dictMode == ZSTD_dictMatchState) {
+ if (isDxS) {
while (ip <= ilimit) {
U32 const current2 = (U32)(ip-base);
U32 const repIndex = current2 - offset_2;
- const BYTE* repMatch = dictMode == ZSTD_dictMatchState
- && repIndex < prefixLowestIndex ?
+ const BYTE* repMatch = repIndex < prefixLowestIndex ?
dictBase - dictIndexDelta + repIndex :
base + repIndex;
if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */)
@@ -925,6 +1849,92 @@ size_t ZSTD_compressBlock_greedy_dictMatchState(
}
+size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch);
+}
+
+size_t ZSTD_compressBlock_lazy_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch);
+}
+
+size_t ZSTD_compressBlock_greedy_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch);
+}
+
+/* Row-based matchfinder */
+size_t ZSTD_compressBlock_lazy2_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_lazy_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_greedy_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict);
+}
+
+size_t ZSTD_compressBlock_lazy2_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_lazy_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState);
+}
+
+size_t ZSTD_compressBlock_greedy_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState);
+}
+
+
+size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch);
+}
+
+size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch);
+}
+
+size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch);
+}
+
FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_lazy_extDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore,
@@ -936,7 +1946,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = iend - 8;
+ const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
const BYTE* const base = ms->window.base;
const U32 dictLimit = ms->window.dictLimit;
const BYTE* const prefixStart = base + dictLimit;
@@ -944,18 +1954,28 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const dictStart = dictBase + ms->window.lowLimit;
const U32 windowLog = ms->cParams.windowLog;
+ const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
typedef size_t (*searchMax_f)(
ZSTD_matchState_t* ms,
const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
- searchMax_f searchMax = searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_extDict_selectMLS : ZSTD_HcFindBestMatch_extDict_selectMLS;
-
+ const searchMax_f searchFuncs[3] = {
+ ZSTD_HcFindBestMatch_extDict_selectMLS,
+ ZSTD_BtFindBestMatch_extDict_selectMLS,
+ ZSTD_RowFindBestMatch_extDict_selectRowLog
+ };
+ searchMax_f searchMax = searchFuncs[(int)searchMethod];
U32 offset_1 = rep[0], offset_2 = rep[1];
- DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic");
+ DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)", (U32)searchMethod);
/* init */
ip += (ip == prefixStart);
+ if (searchMethod == search_rowHash) {
+ ZSTD_row_fillHashCache(ms, base, rowLog,
+ MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */),
+ ms->nextToUpdate, ilimit);
+ }
/* Match Loop */
#if defined(__GNUC__) && defined(__x86_64__)
@@ -968,14 +1988,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
size_t matchLength=0;
size_t offset=0;
const BYTE* start=ip+1;
- U32 current = (U32)(ip-base);
+ U32 curr = (U32)(ip-base);
/* check repCode */
- { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current+1, windowLog);
- const U32 repIndex = (U32)(current+1 - offset_1);
+ { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog);
+ const U32 repIndex = (U32)(curr+1 - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
+ & (offset_1 < curr+1 - windowLow) ) /* note: we are searching at curr+1 */
if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -999,14 +2020,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
if (depth>=1)
while (ip<ilimit) {
ip ++;
- current++;
+ curr++;
/* check repCode */
if (offset) {
- const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog);
- const U32 repIndex = (U32)(current - offset_1);
+ const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
+ const U32 repIndex = (U32)(curr - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1030,14 +2052,15 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
/* let's find an even better one */
if ((depth==2) && (ip<ilimit)) {
ip ++;
- current++;
+ curr++;
/* check repCode */
if (offset) {
- const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog);
- const U32 repIndex = (U32)(current - offset_1);
+ const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
+ const U32 repIndex = (U32)(curr - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1083,7 +2106,8 @@ _storeSequence:
const U32 repIndex = repCurrent - offset_2;
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
- if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */
+ if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
+ & (offset_2 < repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -1136,3 +2160,26 @@ size_t ZSTD_compressBlock_btlazy2_extDict(
{
return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2);
}
+
+size_t ZSTD_compressBlock_greedy_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0);
+}
+
+size_t ZSTD_compressBlock_lazy_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1);
+}
+
+size_t ZSTD_compressBlock_lazy2_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize)
+
+{
+ return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2);
+}
diff --git a/Utilities/cmzstd/lib/compress/zstd_lazy.h b/Utilities/cmzstd/lib/compress/zstd_lazy.h
index 581936f03..150f7b390 100644
--- a/Utilities/cmzstd/lib/compress/zstd_lazy.h
+++ b/Utilities/cmzstd/lib/compress/zstd_lazy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -17,7 +17,18 @@ extern "C" {
#include "zstd_compress_internal.h"
+/**
+ * Dedicated Dictionary Search Structure bucket log. In the
+ * ZSTD_dedicatedDictSearch mode, the hashTable has
+ * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just
+ * one.
+ */
+#define ZSTD_LAZY_DDSS_BUCKET_LOG 2
+
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
+void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip);
+
+void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip);
void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */
@@ -33,6 +44,15 @@ size_t ZSTD_compressBlock_lazy(
size_t ZSTD_compressBlock_greedy(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btlazy2_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -46,6 +66,34 @@ size_t ZSTD_compressBlock_lazy_dictMatchState(
size_t ZSTD_compressBlock_greedy_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_dictMatchState_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+
+size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_dedicatedDictSearch(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_greedy_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -56,9 +104,19 @@ size_t ZSTD_compressBlock_lazy_extDict(
size_t ZSTD_compressBlock_lazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_greedy_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
+size_t ZSTD_compressBlock_lazy2_extDict_row(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize);
size_t ZSTD_compressBlock_btlazy2_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
+
#if defined (__cplusplus)
}
diff --git a/Utilities/cmzstd/lib/compress/zstd_ldm.c b/Utilities/cmzstd/lib/compress/zstd_ldm.c
index 8c4794835..fa4ebeabd 100644
--- a/Utilities/cmzstd/lib/compress/zstd_ldm.c
+++ b/Utilities/cmzstd/lib/compress/zstd_ldm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -11,13 +11,126 @@
#include "zstd_ldm.h"
#include "../common/debug.h"
+#include "../common/xxhash.h"
#include "zstd_fast.h" /* ZSTD_fillHashTable() */
#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
+#include "zstd_ldm_geartab.h"
#define LDM_BUCKET_SIZE_LOG 3
#define LDM_MIN_MATCH_LENGTH 64
#define LDM_HASH_RLOG 7
-#define LDM_HASH_CHAR_OFFSET 10
+
+typedef struct {
+ U64 rolling;
+ U64 stopMask;
+} ldmRollingHashState_t;
+
+/** ZSTD_ldm_gear_init():
+ *
+ * Initializes the rolling hash state such that it will honor the
+ * settings in params. */
+static void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params)
+{
+ unsigned maxBitsInMask = MIN(params->minMatchLength, 64);
+ unsigned hashRateLog = params->hashRateLog;
+
+ state->rolling = ~(U32)0;
+
+ /* The choice of the splitting criterion is subject to two conditions:
+ * 1. it has to trigger on average every 2^(hashRateLog) bytes;
+ * 2. ideally, it has to depend on a window of minMatchLength bytes.
+ *
+ * In the gear hash algorithm, bit n depends on the last n bytes;
+ * so in order to obtain a good quality splitting criterion it is
+ * preferable to use bits with high weight.
+ *
+ * To match condition 1 we use a mask with hashRateLog bits set
+ * and, because of the previous remark, we make sure these bits
+ * have the highest possible weight while still respecting
+ * condition 2.
+ */
+ if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) {
+ state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog);
+ } else {
+ /* In this degenerate case we simply honor the hash rate. */
+ state->stopMask = ((U64)1 << hashRateLog) - 1;
+ }
+}
+
+/** ZSTD_ldm_gear_reset()
+ * Feeds [data, data + minMatchLength) into the hash without registering any
+ * splits. This effectively resets the hash state. This is used when skipping
+ * over data, either at the beginning of a block, or skipping sections.
+ */
+static void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state,
+ BYTE const* data, size_t minMatchLength)
+{
+ U64 hash = state->rolling;
+ size_t n = 0;
+
+#define GEAR_ITER_ONCE() do { \
+ hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
+ n += 1; \
+ } while (0)
+ while (n + 3 < minMatchLength) {
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ }
+ while (n < minMatchLength) {
+ GEAR_ITER_ONCE();
+ }
+#undef GEAR_ITER_ONCE
+}
+
+/** ZSTD_ldm_gear_feed():
+ *
+ * Registers in the splits array all the split points found in the first
+ * size bytes following the data pointer. This function terminates when
+ * either all the data has been processed or LDM_BATCH_SIZE splits are
+ * present in the splits array.
+ *
+ * Precondition: The splits array must not be full.
+ * Returns: The number of bytes processed. */
+static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state,
+ BYTE const* data, size_t size,
+ size_t* splits, unsigned* numSplits)
+{
+ size_t n;
+ U64 hash, mask;
+
+ hash = state->rolling;
+ mask = state->stopMask;
+ n = 0;
+
+#define GEAR_ITER_ONCE() do { \
+ hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
+ n += 1; \
+ if (UNLIKELY((hash & mask) == 0)) { \
+ splits[*numSplits] = n; \
+ *numSplits += 1; \
+ if (*numSplits == LDM_BATCH_SIZE) \
+ goto done; \
+ } \
+ } while (0)
+
+ while (n + 3 < size) {
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ GEAR_ITER_ONCE();
+ }
+ while (n < size) {
+ GEAR_ITER_ONCE();
+ }
+
+#undef GEAR_ITER_ONCE
+
+done:
+ state->rolling = hash;
+ return n;
+}
void ZSTD_ldm_adjustParameters(ldmParams_t* params,
ZSTD_compressionParameters const* cParams)
@@ -27,13 +140,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params,
DEBUGLOG(4, "ZSTD_ldm_adjustParameters");
if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG;
if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH;
- if (cParams->strategy >= ZSTD_btopt) {
- /* Get out of the way of the optimal parser */
- U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength);
- assert(minMatch >= ZSTD_LDM_MINMATCH_MIN);
- assert(minMatch <= ZSTD_LDM_MINMATCH_MAX);
- params->minMatchLength = minMatch;
- }
if (params->hashLog == 0) {
params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG);
assert(params->hashLog <= ZSTD_HASHLOG_MAX);
@@ -61,41 +167,6 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
}
-/** ZSTD_ldm_getSmallHash() :
- * numBits should be <= 32
- * If numBits==0, returns 0.
- * @return : the most significant numBits of value. */
-static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits)
-{
- assert(numBits <= 32);
- return numBits == 0 ? 0 : (U32)(value >> (64 - numBits));
-}
-
-/** ZSTD_ldm_getChecksum() :
- * numBitsToDiscard should be <= 32
- * @return : the next most significant 32 bits after numBitsToDiscard */
-static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard)
-{
- assert(numBitsToDiscard <= 32);
- return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF;
-}
-
-/** ZSTD_ldm_getTag() ;
- * Given the hash, returns the most significant numTagBits bits
- * after (32 + hbits) bits.
- *
- * If there are not enough bits remaining, return the last
- * numTagBits bits. */
-static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits)
-{
- assert(numTagBits < 32 && hbits <= 32);
- if (32 - hbits < numTagBits) {
- return hash & (((U32)1 << numTagBits) - 1);
- } else {
- return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1);
- }
-}
-
/** ZSTD_ldm_getBucket() :
* Returns a pointer to the start of the bucket associated with hash. */
static ldmEntry_t* ZSTD_ldm_getBucket(
@@ -110,38 +181,12 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
size_t const hash, const ldmEntry_t entry,
ldmParams_t const ldmParams)
{
- BYTE* const bucketOffsets = ldmState->bucketOffsets;
- *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry;
- bucketOffsets[hash]++;
- bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1;
-}
+ BYTE* const pOffset = ldmState->bucketOffsets + hash;
+ unsigned const offset = *pOffset;
+
+ *(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry;
+ *pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1));
-/** ZSTD_ldm_makeEntryAndInsertByTag() :
- *
- * Gets the small hash, checksum, and tag from the rollingHash.
- *
- * If the tag matches (1 << ldmParams.hashRateLog)-1, then
- * creates an ldmEntry from the offset, and inserts it into the hash table.
- *
- * hBits is the length of the small hash, which is the most significant hBits
- * of rollingHash. The checksum is the next 32 most significant bits, followed
- * by ldmParams.hashRateLog bits that make up the tag. */
-static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
- U64 const rollingHash,
- U32 const hBits,
- U32 const offset,
- ldmParams_t const ldmParams)
-{
- U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog);
- U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1;
- if (tag == tagMask) {
- U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
- U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
- ldmEntry_t entry;
- entry.offset = offset;
- entry.checksum = checksum;
- ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams);
- }
}
/** ZSTD_ldm_countBackwardsMatch() :
@@ -150,10 +195,10 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
* We count only bytes where pMatch >= pBase and pIn >= pAnchor. */
static size_t ZSTD_ldm_countBackwardsMatch(
const BYTE* pIn, const BYTE* pAnchor,
- const BYTE* pMatch, const BYTE* pBase)
+ const BYTE* pMatch, const BYTE* pMatchBase)
{
size_t matchLength = 0;
- while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) {
+ while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) {
pIn--;
pMatch--;
matchLength++;
@@ -161,6 +206,27 @@ static size_t ZSTD_ldm_countBackwardsMatch(
return matchLength;
}
+/** ZSTD_ldm_countBackwardsMatch_2segments() :
+ * Returns the number of bytes that match backwards from pMatch,
+ * even with the backwards match spanning 2 different segments.
+ *
+ * On reaching `pMatchBase`, start counting from mEnd */
+static size_t ZSTD_ldm_countBackwardsMatch_2segments(
+ const BYTE* pIn, const BYTE* pAnchor,
+ const BYTE* pMatch, const BYTE* pMatchBase,
+ const BYTE* pExtDictStart, const BYTE* pExtDictEnd)
+{
+ size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase);
+ if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) {
+ /* If backwards match is entirely in the extDict or prefix, immediately return */
+ return matchLength;
+ }
+ DEBUGLOG(7, "ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)", matchLength);
+ matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart);
+ DEBUGLOG(7, "final backwards match length = %zu", matchLength);
+ return matchLength;
+}
+
/** ZSTD_ldm_fillFastTables() :
*
* Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.
@@ -198,43 +264,42 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
return 0;
}
-/** ZSTD_ldm_fillLdmHashTable() :
- *
- * Fills hashTable from (lastHashed + 1) to iend (non-inclusive).
- * lastHash is the rolling hash that corresponds to lastHashed.
- *
- * Returns the rolling hash corresponding to position iend-1. */
-static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
- U64 lastHash, const BYTE* lastHashed,
- const BYTE* iend, const BYTE* base,
- U32 hBits, ldmParams_t const ldmParams)
-{
- U64 rollingHash = lastHash;
- const BYTE* cur = lastHashed + 1;
-
- while (cur < iend) {
- rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1],
- cur[ldmParams.minMatchLength-1],
- state->hashPower);
- ZSTD_ldm_makeEntryAndInsertByTag(state,
- rollingHash, hBits,
- (U32)(cur - base), ldmParams);
- ++cur;
- }
- return rollingHash;
-}
-
void ZSTD_ldm_fillHashTable(
- ldmState_t* state, const BYTE* ip,
+ ldmState_t* ldmState, const BYTE* ip,
const BYTE* iend, ldmParams_t const* params)
{
+ U32 const minMatchLength = params->minMatchLength;
+ U32 const hBits = params->hashLog - params->bucketSizeLog;
+ BYTE const* const base = ldmState->window.base;
+ BYTE const* const istart = ip;
+ ldmRollingHashState_t hashState;
+ size_t* const splits = ldmState->splitIndices;
+ unsigned numSplits;
+
DEBUGLOG(5, "ZSTD_ldm_fillHashTable");
- if ((size_t)(iend - ip) >= params->minMatchLength) {
- U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength);
- ZSTD_ldm_fillLdmHashTable(
- state, startingHash, ip, iend - params->minMatchLength, state->window.base,
- params->hashLog - params->bucketSizeLog,
- *params);
+
+ ZSTD_ldm_gear_init(&hashState, params);
+ while (ip < iend) {
+ size_t hashed;
+ unsigned n;
+
+ numSplits = 0;
+ hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits);
+
+ for (n = 0; n < numSplits; n++) {
+ if (ip + splits[n] >= istart + minMatchLength) {
+ BYTE const* const split = ip + splits[n] - minMatchLength;
+ U64 const xxhash = XXH64(split, minMatchLength, 0);
+ U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
+ ldmEntry_t entry;
+
+ entry.offset = (U32)(split - base);
+ entry.checksum = (U32)(xxhash >> 32);
+ ZSTD_ldm_insertEntry(ldmState, hash, entry, *params);
+ }
+ }
+
+ ip += hashed;
}
}
@@ -246,10 +311,10 @@ void ZSTD_ldm_fillHashTable(
* (after a long match, only update tables a limited amount). */
static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor)
{
- U32 const current = (U32)(anchor - ms->window.base);
- if (current > ms->nextToUpdate + 1024) {
+ U32 const curr = (U32)(anchor - ms->window.base);
+ if (curr > ms->nextToUpdate + 1024) {
ms->nextToUpdate =
- current - MIN(512, current - ms->nextToUpdate - 1024);
+ curr - MIN(512, curr - ms->nextToUpdate - 1024);
}
}
@@ -260,11 +325,8 @@ static size_t ZSTD_ldm_generateSequences_internal(
/* LDM parameters */
int const extDict = ZSTD_window_hasExtDict(ldmState->window);
U32 const minMatchLength = params->minMatchLength;
- U64 const hashPower = ldmState->hashPower;
+ U32 const entsPerBucket = 1U << params->bucketSizeLog;
U32 const hBits = params->hashLog - params->bucketSizeLog;
- U32 const ldmBucketSize = 1U << params->bucketSizeLog;
- U32 const hashRateLog = params->hashRateLog;
- U32 const ldmTagMask = (1U << params->hashRateLog) - 1;
/* Prefix and extDict parameters */
U32 const dictLimit = ldmState->window.dictLimit;
U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
@@ -276,45 +338,69 @@ static size_t ZSTD_ldm_generateSequences_internal(
/* Input bounds */
BYTE const* const istart = (BYTE const*)src;
BYTE const* const iend = istart + srcSize;
- BYTE const* const ilimit = iend - MAX(minMatchLength, HASH_READ_SIZE);
+ BYTE const* const ilimit = iend - HASH_READ_SIZE;
/* Input positions */
BYTE const* anchor = istart;
BYTE const* ip = istart;
- /* Rolling hash */
- BYTE const* lastHashed = NULL;
- U64 rollingHash = 0;
-
- while (ip <= ilimit) {
- size_t mLength;
- U32 const current = (U32)(ip - base);
- size_t forwardMatchLength = 0, backwardMatchLength = 0;
- ldmEntry_t* bestEntry = NULL;
- if (ip != istart) {
- rollingHash = ZSTD_rollingHash_rotate(rollingHash, lastHashed[0],
- lastHashed[minMatchLength],
- hashPower);
- } else {
- rollingHash = ZSTD_rollingHash_compute(ip, minMatchLength);
+ /* Rolling hash state */
+ ldmRollingHashState_t hashState;
+ /* Arrays for staged-processing */
+ size_t* const splits = ldmState->splitIndices;
+ ldmMatchCandidate_t* const candidates = ldmState->matchCandidates;
+ unsigned numSplits;
+
+ if (srcSize < minMatchLength)
+ return iend - anchor;
+
+ /* Initialize the rolling hash state with the first minMatchLength bytes */
+ ZSTD_ldm_gear_init(&hashState, params);
+ ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength);
+ ip += minMatchLength;
+
+ while (ip < ilimit) {
+ size_t hashed;
+ unsigned n;
+
+ numSplits = 0;
+ hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip,
+ splits, &numSplits);
+
+ for (n = 0; n < numSplits; n++) {
+ BYTE const* const split = ip + splits[n] - minMatchLength;
+ U64 const xxhash = XXH64(split, minMatchLength, 0);
+ U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
+
+ candidates[n].split = split;
+ candidates[n].hash = hash;
+ candidates[n].checksum = (U32)(xxhash >> 32);
+ candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params);
+ PREFETCH_L1(candidates[n].bucket);
}
- lastHashed = ip;
- /* Do not insert and do not look for a match */
- if (ZSTD_ldm_getTag(rollingHash, hBits, hashRateLog) != ldmTagMask) {
- ip++;
- continue;
- }
+ for (n = 0; n < numSplits; n++) {
+ size_t forwardMatchLength = 0, backwardMatchLength = 0,
+ bestMatchLength = 0, mLength;
+ U32 offset;
+ BYTE const* const split = candidates[n].split;
+ U32 const checksum = candidates[n].checksum;
+ U32 const hash = candidates[n].hash;
+ ldmEntry_t* const bucket = candidates[n].bucket;
+ ldmEntry_t const* cur;
+ ldmEntry_t const* bestEntry = NULL;
+ ldmEntry_t newEntry;
+
+ newEntry.offset = (U32)(split - base);
+ newEntry.checksum = checksum;
+
+ /* If a split point would generate a sequence overlapping with
+ * the previous one, we merely register it in the hash table and
+ * move on */
+ if (split < anchor) {
+ ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
+ continue;
+ }
- /* Get the best entry and compute the match lengths */
- {
- ldmEntry_t* const bucket =
- ZSTD_ldm_getBucket(ldmState,
- ZSTD_ldm_getSmallHash(rollingHash, hBits),
- *params);
- ldmEntry_t* cur;
- size_t bestMatchLength = 0;
- U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
-
- for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
+ for (cur = bucket; cur < bucket + entsPerBucket; cur++) {
size_t curForwardMatchLength, curBackwardMatchLength,
curTotalMatchLength;
if (cur->checksum != checksum || cur->offset <= lowestIndex) {
@@ -328,30 +414,23 @@ static size_t ZSTD_ldm_generateSequences_internal(
cur->offset < dictLimit ? dictEnd : iend;
BYTE const* const lowMatchPtr =
cur->offset < dictLimit ? dictStart : lowPrefixPtr;
-
- curForwardMatchLength = ZSTD_count_2segments(
- ip, pMatch, iend,
- matchEnd, lowPrefixPtr);
+ curForwardMatchLength =
+ ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr);
if (curForwardMatchLength < minMatchLength) {
continue;
}
- curBackwardMatchLength =
- ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch,
- lowMatchPtr);
- curTotalMatchLength = curForwardMatchLength +
- curBackwardMatchLength;
+ curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(
+ split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd);
} else { /* !extDict */
BYTE const* const pMatch = base + cur->offset;
- curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
+ curForwardMatchLength = ZSTD_count(split, pMatch, iend);
if (curForwardMatchLength < minMatchLength) {
continue;
}
curBackwardMatchLength =
- ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch,
- lowPrefixPtr);
- curTotalMatchLength = curForwardMatchLength +
- curBackwardMatchLength;
+ ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr);
}
+ curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength;
if (curTotalMatchLength > bestMatchLength) {
bestMatchLength = curTotalMatchLength;
@@ -360,57 +439,54 @@ static size_t ZSTD_ldm_generateSequences_internal(
bestEntry = cur;
}
}
- }
-
- /* No match found -- continue searching */
- if (bestEntry == NULL) {
- ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
- hBits, current,
- *params);
- ip++;
- continue;
- }
- /* Match found */
- mLength = forwardMatchLength + backwardMatchLength;
- ip -= backwardMatchLength;
+ /* No match found -- insert an entry into the hash table
+ * and process the next candidate match */
+ if (bestEntry == NULL) {
+ ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
+ continue;
+ }
- {
- /* Store the sequence:
- * ip = current - backwardMatchLength
- * The match is at (bestEntry->offset - backwardMatchLength)
- */
- U32 const matchIndex = bestEntry->offset;
- U32 const offset = current - matchIndex;
- rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
-
- /* Out of sequence storage */
- if (rawSeqStore->size == rawSeqStore->capacity)
- return ERROR(dstSize_tooSmall);
- seq->litLength = (U32)(ip - anchor);
- seq->matchLength = (U32)mLength;
- seq->offset = offset;
- rawSeqStore->size++;
- }
+ /* Match found */
+ offset = (U32)(split - base) - bestEntry->offset;
+ mLength = forwardMatchLength + backwardMatchLength;
+ {
+ rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
+
+ /* Out of sequence storage */
+ if (rawSeqStore->size == rawSeqStore->capacity)
+ return ERROR(dstSize_tooSmall);
+ seq->litLength = (U32)(split - backwardMatchLength - anchor);
+ seq->matchLength = (U32)mLength;
+ seq->offset = offset;
+ rawSeqStore->size++;
+ }
- /* Insert the current entry into the hash table */
- ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
- (U32)(lastHashed - base),
- *params);
+ /* Insert the current entry into the hash table --- it must be
+ * done after the previous block to avoid clobbering bestEntry */
+ ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
- assert(ip + backwardMatchLength == lastHashed);
+ anchor = split + forwardMatchLength;
- /* Fill the hash table from lastHashed+1 to ip+mLength*/
- /* Heuristic: don't need to fill the entire table at end of block */
- if (ip + mLength <= ilimit) {
- rollingHash = ZSTD_ldm_fillLdmHashTable(
- ldmState, rollingHash, lastHashed,
- ip + mLength, base, hBits, *params);
- lastHashed = ip + mLength - 1;
+ /* If we find a match that ends after the data that we've hashed
+ * then we have a repeating, overlapping, pattern. E.g. all zeros.
+ * If one repetition of the pattern matches our `stopMask` then all
+ * repetitions will. We don't need to insert them all into out table,
+ * only the first one. So skip over overlapping matches.
+ * This is a major speed boost (20x) for compressing a single byte
+ * repeated, when that byte ends up in the table.
+ */
+ if (anchor > ip + hashed) {
+ ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);
+ /* Continue the outter loop at anchor (ip + hashed == anchor). */
+ ip = anchor - hashed;
+ break;
+ }
}
- ip += mLength;
- anchor = ip;
+
+ ip += hashed;
}
+
return iend - anchor;
}
@@ -459,7 +535,7 @@ size_t ZSTD_ldm_generateSequences(
assert(chunkStart < iend);
/* 1. Perform overflow correction if necessary. */
- if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
+ if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) {
U32 const ldmHSize = 1U << params->hashLog;
U32 const correction = ZSTD_window_correctOverflow(
&ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
@@ -562,14 +638,32 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore,
return sequence;
}
+void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
+ U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
+ while (currPos && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
+ if (currPos >= currSeq.litLength + currSeq.matchLength) {
+ currPos -= currSeq.litLength + currSeq.matchLength;
+ rawSeqStore->pos++;
+ } else {
+ rawSeqStore->posInSequence = currPos;
+ break;
+ }
+ }
+ if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
+ rawSeqStore->posInSequence = 0;
+ }
+}
+
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
void const* src, size_t srcSize)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
unsigned const minMatch = cParams->minMatch;
ZSTD_blockCompressor const blockCompressor =
- ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms));
+ ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms));
/* Input bounds */
BYTE const* const istart = (BYTE const*)src;
BYTE const* const iend = istart + srcSize;
@@ -577,9 +671,18 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
BYTE const* ip = istart;
DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize);
+ /* If using opt parser, use LDMs only as candidates rather than always accepting them */
+ if (cParams->strategy >= ZSTD_btopt) {
+ size_t lastLLSize;
+ ms->ldmSeqStore = rawSeqStore;
+ lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);
+ ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);
+ return lastLLSize;
+ }
+
assert(rawSeqStore->pos <= rawSeqStore->size);
assert(rawSeqStore->size <= rawSeqStore->capacity);
- /* Loop through each sequence and apply the block compressor to the lits */
+ /* Loop through each sequence and apply the block compressor to the literals */
while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {
/* maybeSplitSequence updates rawSeqStore->pos */
rawSeq const sequence = maybeSplitSequence(rawSeqStore,
diff --git a/Utilities/cmzstd/lib/compress/zstd_ldm.h b/Utilities/cmzstd/lib/compress/zstd_ldm.h
index 229ea05a9..393466fa9 100644
--- a/Utilities/cmzstd/lib/compress/zstd_ldm.h
+++ b/Utilities/cmzstd/lib/compress/zstd_ldm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -66,6 +66,7 @@ size_t ZSTD_ldm_generateSequences(
*/
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
void const* src, size_t srcSize);
/**
@@ -73,11 +74,17 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
*
* Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.
* Avoids emitting matches less than `minMatch` bytes.
- * Must be called for data with is not passed to ZSTD_ldm_blockCompress().
+ * Must be called for data that is not passed to ZSTD_ldm_blockCompress().
*/
void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize,
U32 const minMatch);
+/* ZSTD_ldm_skipRawSeqStoreBytes():
+ * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.
+ * Not to be used in conjunction with ZSTD_ldm_skipSequences().
+ * Must be called for data with is not passed to ZSTD_ldm_blockCompress().
+ */
+void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes);
/** ZSTD_ldm_getTableSize() :
* Estimate the space needed for long distance matching tables or 0 if LDM is
diff --git a/Utilities/cmzstd/lib/compress/zstd_ldm_geartab.h b/Utilities/cmzstd/lib/compress/zstd_ldm_geartab.h
new file mode 100644
index 000000000..e5c24d856
--- /dev/null
+++ b/Utilities/cmzstd/lib/compress/zstd_ldm_geartab.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_LDM_GEARTAB_H
+#define ZSTD_LDM_GEARTAB_H
+
+static U64 ZSTD_ldm_gearTab[256] = {
+ 0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,
+ 0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,
+ 0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,
+ 0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889,
+ 0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e,
+ 0x37b628620b628, 0x49a8d455d88caf5, 0x8556d711e6958140,
+ 0x4f7ae74fc605c1f, 0x829f0c3468bd3a20, 0x4ffdc885c625179e,
+ 0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f,
+ 0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391,
+ 0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210,
+ 0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be,
+ 0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a,
+ 0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b,
+ 0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4,
+ 0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb,
+ 0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312,
+ 0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01,
+ 0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc,
+ 0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967,
+ 0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553,
+ 0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f,
+ 0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2,
+ 0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d,
+ 0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a,
+ 0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74,
+ 0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3,
+ 0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1,
+ 0xff452823dbb010a, 0x9d42ed614f3dd267, 0x5b9313c06257c57b,
+ 0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568,
+ 0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a,
+ 0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1,
+ 0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9,
+ 0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463,
+ 0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba,
+ 0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9,
+ 0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61,
+ 0x24a5483879c453e3, 0x88026889192b4b9, 0x28da96671782dbec,
+ 0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6,
+ 0xbc135a0a704b70ba, 0x69cd868f7622ada, 0xbc37ba89e0b9c0ab,
+ 0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5,
+ 0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59,
+ 0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7,
+ 0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc,
+ 0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb,
+ 0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be,
+ 0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312,
+ 0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1,
+ 0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc,
+ 0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d,
+ 0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445,
+ 0x820d471e20b348e, 0x1874383cb83d46dc, 0x97edeec7a1efe11c,
+ 0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5,
+ 0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5,
+ 0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28,
+ 0xaf846af6ab7d0bf4, 0xe5af208eb666e49, 0x5e6622f73534cd6a,
+ 0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9,
+ 0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15,
+ 0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef,
+ 0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2,
+ 0x9f90e4c5fd508d8, 0xa34e5956fbaf3385, 0x2e2f8e151d3ef375,
+ 0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3,
+ 0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595,
+ 0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389,
+ 0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4,
+ 0x4228e364c5b5ed7, 0x9d7a3edf0da43911, 0x8edcfeda24686756,
+ 0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc,
+ 0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45,
+ 0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea,
+ 0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f,
+ 0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc,
+ 0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c,
+ 0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a,
+ 0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17,
+ 0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3,
+ 0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4,
+ 0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91,
+ 0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40,
+ 0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741,
+ 0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f,
+ 0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4,
+ 0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad,
+ 0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047,
+ 0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2,
+ 0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e,
+ 0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b,
+ 0x2b4da14f2613d8f4
+};
+
+#endif /* ZSTD_LDM_GEARTAB_H */
diff --git a/Utilities/cmzstd/lib/compress/zstd_opt.c b/Utilities/cmzstd/lib/compress/zstd_opt.c
index 36fff050c..402a7e5c7 100644
--- a/Utilities/cmzstd/lib/compress/zstd_opt.c
+++ b/Utilities/cmzstd/lib/compress/zstd_opt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
+ * Copyright (c) Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -386,32 +386,32 @@ static U32 ZSTD_insertBt1(
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
const BYTE* match;
- const U32 current = (U32)(ip-base);
- const U32 btLow = btMask >= current ? 0 : current - btMask;
- U32* smallerPtr = bt + 2*(current&btMask);
+ const U32 curr = (U32)(ip-base);
+ const U32 btLow = btMask >= curr ? 0 : curr - btMask;
+ U32* smallerPtr = bt + 2*(curr&btMask);
U32* largerPtr = smallerPtr + 1;
U32 dummy32; /* to be nullified at the end */
U32 const windowLow = ms->window.lowLimit;
- U32 matchEndIdx = current+8+1;
+ U32 matchEndIdx = curr+8+1;
size_t bestLength = 8;
U32 nbCompares = 1U << cParams->searchLog;
#ifdef ZSTD_C_PREDICT
- U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
- U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
+ U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0);
+ U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1);
predictedSmall += (predictedSmall>0);
predictedLarge += (predictedLarge>0);
#endif /* ZSTD_C_PREDICT */
- DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current);
+ DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr);
assert(ip <= iend-8); /* required for h calculation */
- hashTable[h] = current; /* Update Hash Table */
+ hashTable[h] = curr; /* Update Hash Table */
assert(windowLow > 0);
while (nbCompares-- && (matchIndex >= windowLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- assert(matchIndex < current);
+ assert(matchIndex < curr);
#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */
const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
@@ -474,8 +474,8 @@ static U32 ZSTD_insertBt1(
*smallerPtr = *largerPtr = 0;
{ U32 positions = 0;
if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */
- assert(matchEndIdx > current + 8);
- return MAX(positions, matchEndIdx - (current + 8));
+ assert(matchEndIdx > curr + 8);
+ return MAX(positions, matchEndIdx - (curr + 8));
}
}
@@ -519,7 +519,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
const BYTE* const base = ms->window.base;
- U32 const current = (U32)(ip-base);
+ U32 const curr = (U32)(ip-base);
U32 const hashLog = cParams->hashLog;
U32 const minMatch = (mls==3) ? 3 : 4;
U32* const hashTable = ms->hashTable;
@@ -533,12 +533,12 @@ U32 ZSTD_insertBtAndGetAllMatches (
U32 const dictLimit = ms->window.dictLimit;
const BYTE* const dictEnd = dictBase + dictLimit;
const BYTE* const prefixStart = base + dictLimit;
- U32 const btLow = (btMask >= current) ? 0 : current - btMask;
- U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog);
+ U32 const btLow = (btMask >= curr) ? 0 : curr - btMask;
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);
U32 const matchLow = windowLow ? windowLow : 1;
- U32* smallerPtr = bt + 2*(current&btMask);
- U32* largerPtr = bt + 2*(current&btMask) + 1;
- U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */
+ U32* smallerPtr = bt + 2*(curr&btMask);
+ U32* largerPtr = bt + 2*(curr&btMask) + 1;
+ U32 matchEndIdx = curr+8+1; /* farthest referenced position of any match => detects repetitive patterns */
U32 dummy32; /* to be nullified at the end */
U32 mnum = 0;
U32 nbCompares = 1U << cParams->searchLog;
@@ -557,7 +557,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;
size_t bestLength = lengthToBeat-1;
- DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current);
+ DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", curr);
/* check repCode */
assert(ll0 <= 1); /* necessarily 1 or 0 */
@@ -565,29 +565,29 @@ U32 ZSTD_insertBtAndGetAllMatches (
U32 repCode;
for (repCode = ll0; repCode < lastR; repCode++) {
U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
- U32 const repIndex = current - repOffset;
+ U32 const repIndex = curr - repOffset;
U32 repLen = 0;
- assert(current >= dictLimit);
- if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */
+ assert(curr >= dictLimit);
+ if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) { /* equivalent to `curr > repIndex >= dictLimit` */
/* We must validate the repcode offset because when we're using a dictionary the
* valid offset range shrinks when the dictionary goes out of bounds.
*/
if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {
repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;
}
- } else { /* repIndex < dictLimit || repIndex >= current */
+ } else { /* repIndex < dictLimit || repIndex >= curr */
const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ?
dmsBase + repIndex - dmsIndexDelta :
dictBase + repIndex;
- assert(current >= windowLow);
+ assert(curr >= windowLow);
if ( dictMode == ZSTD_extDict
- && ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */
+ && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */
& (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */)
&& (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch;
}
if (dictMode == ZSTD_dictMatchState
- && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */
+ && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */
& ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */
&& (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch;
@@ -609,7 +609,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
if ((mls == 3) /*static*/ && (bestLength < mls)) {
U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);
if ((matchIndex3 >= matchLow)
- & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
+ & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {
size_t mlen;
if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) {
const BYTE* const match = base + matchIndex3;
@@ -624,26 +624,26 @@ U32 ZSTD_insertBtAndGetAllMatches (
DEBUGLOG(8, "found small match with hlog3, of length %u",
(U32)mlen);
bestLength = mlen;
- assert(current > matchIndex3);
+ assert(curr > matchIndex3);
assert(mnum==0); /* no prior solution */
- matches[0].off = (current - matchIndex3) + ZSTD_REP_MOVE;
+ matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE;
matches[0].len = (U32)mlen;
mnum = 1;
if ( (mlen > sufficient_len) |
(ip+mlen == iLimit) ) { /* best possible length */
- ms->nextToUpdate = current+1; /* skip insertion */
+ ms->nextToUpdate = curr+1; /* skip insertion */
return 1;
} } }
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
}
- hashTable[h] = current; /* Update Hash Table */
+ hashTable[h] = curr; /* Update Hash Table */
while (nbCompares-- && (matchIndex >= matchLow)) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
const BYTE* match;
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- assert(current > matchIndex);
+ assert(curr > matchIndex);
if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {
assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */
@@ -660,12 +660,12 @@ U32 ZSTD_insertBtAndGetAllMatches (
if (matchLength > bestLength) {
DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
- (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
+ (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
assert(matchEndIdx > matchIndex);
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
bestLength = matchLength;
- matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
+ matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
matches[mnum].len = (U32)matchLength;
mnum++;
if ( (matchLength > ZSTD_OPT_NUM)
@@ -708,11 +708,11 @@ U32 ZSTD_insertBtAndGetAllMatches (
if (matchLength > bestLength) {
matchIndex = dictMatchIndex + dmsIndexDelta;
DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
- (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE);
+ (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
bestLength = matchLength;
- matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE;
+ matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
matches[mnum].len = (U32)matchLength;
mnum++;
if ( (matchLength > ZSTD_OPT_NUM)
@@ -733,7 +733,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
}
}
- assert(matchEndIdx > current+8);
+ assert(matchEndIdx > curr+8);
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
return mnum;
}
@@ -764,6 +764,140 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
}
}
+/*************************
+* LDM helper functions *
+*************************/
+
+/* Struct containing info needed to make decision about ldm inclusion */
+typedef struct {
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
+ U32 startPosInBlock; /* Start position of the current match candidate */
+ U32 endPosInBlock; /* End position of the current match candidate */
+ U32 offset; /* Offset of the match candidate */
+} ZSTD_optLdm_t;
+
+/* ZSTD_optLdm_skipRawSeqStoreBytes():
+ * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
+ */
+static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
+ U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
+ while (currPos && rawSeqStore->pos < rawSeqStore->size) {
+ rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
+ if (currPos >= currSeq.litLength + currSeq.matchLength) {
+ currPos -= currSeq.litLength + currSeq.matchLength;
+ rawSeqStore->pos++;
+ } else {
+ rawSeqStore->posInSequence = currPos;
+ break;
+ }
+ }
+ if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {
+ rawSeqStore->posInSequence = 0;
+ }
+}
+
+/* ZSTD_opt_getNextMatchAndUpdateSeqStore():
+ * Calculates the beginning and end of the next match in the current block.
+ * Updates 'pos' and 'posInSequence' of the ldmSeqStore.
+ */
+static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
+ U32 blockBytesRemaining) {
+ rawSeq currSeq;
+ U32 currBlockEndPos;
+ U32 literalsBytesRemaining;
+ U32 matchBytesRemaining;
+
+ /* Setting match end position to MAX to ensure we never use an LDM during this block */
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
+ optLdm->startPosInBlock = UINT_MAX;
+ optLdm->endPosInBlock = UINT_MAX;
+ return;
+ }
+ /* Calculate appropriate bytes left in matchLength and litLength after adjusting
+ based on ldmSeqStore->posInSequence */
+ currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
+ assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
+ currBlockEndPos = currPosInBlock + blockBytesRemaining;
+ literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ?
+ currSeq.litLength - (U32)optLdm->seqStore.posInSequence :
+ 0;
+ matchBytesRemaining = (literalsBytesRemaining == 0) ?
+ currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) :
+ currSeq.matchLength;
+
+ /* If there are more literal bytes than bytes remaining in block, no ldm is possible */
+ if (literalsBytesRemaining >= blockBytesRemaining) {
+ optLdm->startPosInBlock = UINT_MAX;
+ optLdm->endPosInBlock = UINT_MAX;
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining);
+ return;
+ }
+
+ /* Matches may be < MINMATCH by this process. In that case, we will reject them
+ when we are deciding whether or not to add the ldm */
+ optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining;
+ optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining;
+ optLdm->offset = currSeq.offset;
+
+ if (optLdm->endPosInBlock > currBlockEndPos) {
+ /* Match ends after the block ends, we can't use the whole match */
+ optLdm->endPosInBlock = currBlockEndPos;
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock);
+ } else {
+ /* Consume nb of bytes equal to size of sequence left */
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining);
+ }
+}
+
+/* ZSTD_optLdm_maybeAddMatch():
+ * Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
+ * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
+ */
+static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
+ ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
+ U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
+ /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
+ U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
+ U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
+
+ /* Ensure that current block position is not outside of the match */
+ if (currPosInBlock < optLdm->startPosInBlock
+ || currPosInBlock >= optLdm->endPosInBlock
+ || candidateMatchLength < MINMATCH) {
+ return;
+ }
+
+ if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
+ DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
+ candidateOffCode, candidateMatchLength, currPosInBlock);
+ matches[*nbMatches].len = candidateMatchLength;
+ matches[*nbMatches].off = candidateOffCode;
+ (*nbMatches)++;
+ }
+}
+
+/* ZSTD_optLdm_processMatchCandidate():
+ * Wrapper function to update ldm seq store and call ldm functions as necessary.
+ */
+static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
+ U32 currPosInBlock, U32 remainingBytes) {
+ if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
+ return;
+ }
+
+ if (currPosInBlock >= optLdm->endPosInBlock) {
+ if (currPosInBlock > optLdm->endPosInBlock) {
+ /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily
+ * at the end of a match from the ldm seq store, and will often be some bytes
+ * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
+ */
+ U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
+ ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
+ }
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
+ }
+ ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
+}
/*-*******************************
* Optimal parser
@@ -817,6 +951,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
ZSTD_optimal_t* const opt = optStatePtr->priceTable;
ZSTD_match_t* const matches = optStatePtr->matchTable;
ZSTD_optimal_t lastSequence;
+ ZSTD_optLdm_t optLdm;
+
+ optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;
+ optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;
+ ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));
/* init */
DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u",
@@ -832,7 +971,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* find first match */
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
- U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
+ (U32)(ip-istart), (U32)(iend - ip));
if (!nbMatches) { ip++; continue; }
/* initialize opt[0] */
@@ -925,9 +1066,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
if (opt[cur].mlen != 0) {
U32 const prev = cur - opt[cur].mlen;
repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
- memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
+ ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
} else {
- memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
+ ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
}
/* last match must start at a minimum distance of 8 from oend */
@@ -945,8 +1086,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
U32 const previousPrice = opt[cur].price;
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
- U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
+ U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
U32 matchNb;
+
+ ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
+ (U32)(inr-istart), (U32)(iend-inr));
+
if (!nbMatches) {
DEBUGLOG(7, "rPos:%u : no match found", cur);
continue;
@@ -1010,9 +1155,9 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
*/
if (lastSequence.mlen != 0) {
repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
- memcpy(rep, &reps, sizeof(reps));
+ ZSTD_memcpy(rep, &reps, sizeof(reps));
} else {
- memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
+ ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
}
{ U32 const storeEnd = cur + 1;
@@ -1110,7 +1255,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
const void* src, size_t srcSize)
{
U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */
- memcpy(tmpRep, rep, sizeof(tmpRep));
+ ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));
DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize);
assert(ms->opt.litLengthSum == 0); /* first block */
@@ -1143,7 +1288,7 @@ size_t ZSTD_compressBlock_btultra2(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
- U32 const current = (U32)((const BYTE*)src - ms->window.base);
+ U32 const curr = (U32)((const BYTE*)src - ms->window.base);
DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize);
/* 2-pass strategy:
@@ -1158,7 +1303,7 @@ size_t ZSTD_compressBlock_btultra2(
if ( (ms->opt.litLengthSum==0) /* first block */
&& (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
&& (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */
- && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
+ && (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
&& (srcSize > ZSTD_PREDEF_THRESHOLD)
) {
ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);
diff --git a/Utilities/cmzstd/lib/compress/zstd_opt.h b/Utilities/cmzstd/lib/compress/zstd_opt.h
index 9aba8a901..627255f53 100644
--- a/Utilities/cmzstd/lib/compress/zstd_opt.h
+++ b/Utilities/cmzstd/lib/compress/zstd_opt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/compress/zstdmt_compress.c b/Utilities/cmzstd/lib/compress/zstdmt_compress.c
index 1e3c8fdbe..22aa3e124 100644
--- a/Utilities/cmzstd/lib/compress/zstdmt_compress.c
+++ b/Utilities/cmzstd/lib/compress/zstdmt_compress.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -20,8 +20,7 @@
/* ====== Dependencies ====== */
-#include <string.h> /* memcpy, memset */
-#include <limits.h> /* INT_MAX, UINT_MAX */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */
#include "../common/mem.h" /* MEM_STATIC */
#include "../common/pool.h" /* threadpool */
#include "../common/threading.h" /* mutex */
@@ -106,11 +105,11 @@ typedef struct ZSTDMT_bufferPool_s {
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem)
{
unsigned const maxNbBuffers = 2*nbWorkers + 3;
- ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
+ ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
if (bufPool==NULL) return NULL;
if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
- ZSTD_free(bufPool, cMem);
+ ZSTD_customFree(bufPool, cMem);
return NULL;
}
bufPool->bufferSize = 64 KB;
@@ -127,10 +126,10 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
if (!bufPool) return; /* compatibility with free on NULL */
for (u=0; u<bufPool->totalBuffers; u++) {
DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
- ZSTD_free(bufPool->bTable[u].start, bufPool->cMem);
+ ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem);
}
ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
- ZSTD_free(bufPool, bufPool->cMem);
+ ZSTD_customFree(bufPool, bufPool->cMem);
}
/* only works at initialization, not during compression */
@@ -201,13 +200,13 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
}
/* size conditions not respected : scratch this buffer, create new one */
DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing");
- ZSTD_free(buf.start, bufPool->cMem);
+ ZSTD_customFree(buf.start, bufPool->cMem);
}
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
/* create new buffer */
DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer");
{ buffer_t buffer;
- void* const start = ZSTD_malloc(bSize, bufPool->cMem);
+ void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
buffer.start = start; /* note : start can be NULL if malloc fails ! */
buffer.capacity = (start==NULL) ? 0 : bSize;
if (start==NULL) {
@@ -229,13 +228,13 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
{
size_t const bSize = bufPool->bufferSize;
if (buffer.capacity < bSize) {
- void* const start = ZSTD_malloc(bSize, bufPool->cMem);
+ void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
buffer_t newBuffer;
newBuffer.start = start;
newBuffer.capacity = start == NULL ? 0 : bSize;
if (start != NULL) {
assert(newBuffer.capacity >= buffer.capacity);
- memcpy(newBuffer.start, buffer.start, buffer.capacity);
+ ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity);
DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize);
return newBuffer;
}
@@ -261,14 +260,12 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
/* Reached bufferPool capacity (should not happen) */
DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing ");
- ZSTD_free(buf.start, bufPool->cMem);
+ ZSTD_customFree(buf.start, bufPool->cMem);
}
/* ===== Seq Pool Wrapper ====== */
-static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0};
-
typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
@@ -278,7 +275,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
static rawSeqStore_t bufferToSeq(buffer_t buffer)
{
- rawSeqStore_t seq = {NULL, 0, 0, 0};
+ rawSeqStore_t seq = kNullRawSeqStore;
seq.seq = (rawSeq*)buffer.start;
seq.capacity = buffer.capacity / sizeof(rawSeq);
return seq;
@@ -354,7 +351,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
for (cid=0; cid<pool->totalCCtx; cid++)
ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
ZSTD_pthread_mutex_destroy(&pool->poolMutex);
- ZSTD_free(pool, pool->cMem);
+ ZSTD_customFree(pool, pool->cMem);
}
/* ZSTDMT_createCCtxPool() :
@@ -362,12 +359,12 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
ZSTD_customMem cMem)
{
- ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
+ ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc(
sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
assert(nbWorkers > 0);
if (!cctxPool) return NULL;
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
- ZSTD_free(cctxPool, cMem);
+ ZSTD_customFree(cctxPool, cMem);
return NULL;
}
cctxPool->cMem = cMem;
@@ -475,10 +472,8 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
assert(params.ldmParams.hashRateLog < 32);
- serialState->ldmState.hashPower =
- ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
} else {
- memset(&params.ldmParams, 0, sizeof(params.ldmParams));
+ ZSTD_memset(&params.ldmParams, 0, sizeof(params.ldmParams));
}
serialState->nextJobID = 0;
if (params.fParams.checksumFlag)
@@ -489,35 +484,35 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
unsigned const bucketLog =
params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
- size_t const bucketSize = (size_t)1 << bucketLog;
unsigned const prevBucketLog =
serialState->params.ldmParams.hashLog -
serialState->params.ldmParams.bucketSizeLog;
+ size_t const numBuckets = (size_t)1 << bucketLog;
/* Size the seq pool tables */
ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
/* Reset the window */
ZSTD_window_init(&serialState->ldmState.window);
/* Resize tables and output space if necessary. */
if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
- ZSTD_free(serialState->ldmState.hashTable, cMem);
- serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_malloc(hashSize, cMem);
+ ZSTD_customFree(serialState->ldmState.hashTable, cMem);
+ serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem);
}
if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
- ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
- serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_malloc(bucketSize, cMem);
+ ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
+ serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);
}
if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
return 1;
/* Zero the tables */
- memset(serialState->ldmState.hashTable, 0, hashSize);
- memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
+ ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);
+ ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);
/* Update window state and fill hash table with dict */
serialState->ldmState.loadedDictEnd = 0;
if (dictSize > 0) {
if (dictContentType == ZSTD_dct_rawContent) {
BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
- ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
+ ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);
ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, &params.ldmParams);
serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
} else {
@@ -537,7 +532,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
static int ZSTDMT_serialState_init(serialState_t* serialState)
{
int initError = 0;
- memset(serialState, 0, sizeof(*serialState));
+ ZSTD_memset(serialState, 0, sizeof(*serialState));
initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
@@ -552,8 +547,8 @@ static void ZSTDMT_serialState_free(serialState_t* serialState)
ZSTD_pthread_cond_destroy(&serialState->cond);
ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
- ZSTD_free(serialState->ldmState.hashTable, cMem);
- ZSTD_free(serialState->ldmState.bucketOffsets, cMem);
+ ZSTD_customFree(serialState->ldmState.hashTable, cMem);
+ ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
}
static void ZSTDMT_serialState_update(serialState_t* serialState,
@@ -574,7 +569,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
seqStore.size == 0 && seqStore.capacity > 0);
assert(src.size <= serialState->params.jobSize);
- ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
+ ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);
error = ZSTD_ldm_generateSequences(
&serialState->ldmState, &seqStore,
&serialState->params.ldmParams, src.start, src.size);
@@ -686,6 +681,8 @@ static void ZSTDMT_compressionJob(void* jobDescription)
if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
/* Don't run LDM for the chunks, since we handle it externally */
jobParams.ldmParams.enableLdm = 0;
+ /* Correct nbWorkers to 0. */
+ jobParams.nbWorkers = 0;
/* init */
@@ -698,6 +695,10 @@ static void ZSTDMT_compressionJob(void* jobDescription)
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
}
+ if (!job->firstJob) {
+ size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);
+ if (ZSTD_isError(err)) JOB_ERROR(err);
+ }
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
ZSTD_dtlm_fast,
@@ -753,6 +754,13 @@ static void ZSTDMT_compressionJob(void* jobDescription)
if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
lastCBlockSize = cSize;
} }
+ if (!job->firstJob) {
+ /* Double check that we don't have an ext-dict, because then our
+ * repcode invalidation doesn't work.
+ */
+ assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
+ }
+ ZSTD_CCtx_trace(cctx, 0);
_endJob:
ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
@@ -820,7 +828,6 @@ struct ZSTDMT_CCtx_s {
roundBuff_t roundBuff;
serialState_t serial;
rsyncState_t rsync;
- unsigned singleBlockingThread;
unsigned jobIDMask;
unsigned doneJobID;
unsigned nextJobID;
@@ -832,6 +839,7 @@ struct ZSTDMT_CCtx_s {
ZSTD_customMem cMem;
ZSTD_CDict* cdictLocal;
const ZSTD_CDict* cdict;
+ unsigned providedFactory: 1;
};
static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)
@@ -842,7 +850,7 @@ static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZS
ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);
ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);
}
- ZSTD_free(jobTable, cMem);
+ ZSTD_customFree(jobTable, cMem);
}
/* ZSTDMT_allocJobsTable()
@@ -854,7 +862,7 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom
U32 const nbJobs = 1 << nbJobsLog2;
U32 jobNb;
ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)
- ZSTD_calloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
+ ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
int initError = 0;
if (jobTable==NULL) return NULL;
*nbJobsPtr = nbJobs;
@@ -885,12 +893,12 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
/* ZSTDMT_CCtxParam_setNbWorkers():
* Internal use only */
-size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
+static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
{
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
}
-MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
+MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
{
ZSTDMT_CCtx* mtctx;
U32 nbJobs = nbWorkers + 2;
@@ -903,12 +911,19 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
/* invalid custom allocator */
return NULL;
- mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
+ mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem);
if (!mtctx) return NULL;
ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);
mtctx->cMem = cMem;
mtctx->allJobsCompleted = 1;
- mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
+ if (pool != NULL) {
+ mtctx->factory = pool;
+ mtctx->providedFactory = 1;
+ }
+ else {
+ mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
+ mtctx->providedFactory = 0;
+ }
mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
mtctx->jobIDMask = nbJobs - 1;
@@ -925,22 +940,18 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
return mtctx;
}
-ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
+ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
{
#ifdef ZSTD_MULTITHREAD
- return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
+ return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool);
#else
(void)nbWorkers;
(void)cMem;
+ (void)pool;
return NULL;
#endif
}
-ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
-{
- return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
-}
-
/* ZSTDMT_releaseAllJobResources() :
* note : ensure all workers are killed first ! */
@@ -957,7 +968,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
/* Clear the job description, but keep the mutex/cond */
- memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
+ ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
mtctx->jobs[jobID].job_mutex = mutex;
mtctx->jobs[jobID].job_cond = cond;
}
@@ -984,7 +995,8 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
{
if (mtctx==NULL) return 0; /* compatible with free on NULL */
- POOL_free(mtctx->factory); /* stop and free worker threads */
+ if (!mtctx->providedFactory)
+ POOL_free(mtctx->factory); /* stop and free worker threads */
ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
ZSTDMT_freeBufferPool(mtctx->bufPool);
@@ -993,8 +1005,8 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
ZSTDMT_serialState_free(&mtctx->serial);
ZSTD_freeCDict(mtctx->cdictLocal);
if (mtctx->roundBuff.buffer)
- ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
- ZSTD_free(mtctx, mtctx->cMem);
+ ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
+ ZSTD_customFree(mtctx, mtctx->cMem);
return 0;
}
@@ -1011,65 +1023,6 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
+ mtctx->roundBuff.capacity;
}
-/* Internal only */
-size_t
-ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
- ZSTDMT_parameter parameter,
- int value)
-{
- DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter");
- switch(parameter)
- {
- case ZSTDMT_p_jobSize :
- DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
- case ZSTDMT_p_overlapLog :
- DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
- case ZSTDMT_p_rsyncable :
- DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
- return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
- default :
- return ERROR(parameter_unsupported);
- }
-}
-
-size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value)
-{
- DEBUGLOG(4, "ZSTDMT_setMTCtxParameter");
- return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
-}
-
-size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value)
-{
- switch (parameter) {
- case ZSTDMT_p_jobSize:
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
- case ZSTDMT_p_overlapLog:
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
- case ZSTDMT_p_rsyncable:
- return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
- default:
- return ERROR(parameter_unsupported);
- }
-}
-
-/* Sets parameters relevant to the compression job,
- * initializing others to default values. */
-static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params)
-{
- ZSTD_CCtx_params jobParams = *params;
- /* Clear parameters related to multithreading */
- jobParams.forceWindow = 0;
- jobParams.nbWorkers = 0;
- jobParams.jobSize = 0;
- jobParams.overlapLog = 0;
- jobParams.rsyncable = 0;
- memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
- memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
- return jobParams;
-}
-
/* ZSTDMT_resize() :
* @return : error code if fails, 0 on success */
@@ -1098,7 +1051,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)",
compressionLevel);
mtctx->params.compressionLevel = compressionLevel;
- { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0);
+ { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
cParams.windowLog = saved_wlog;
mtctx->params.cParams = cParams;
}
@@ -1185,8 +1138,8 @@ static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)
if (params->ldmParams.enableLdm) {
/* In Long Range Mode, the windowLog is typically oversized.
* In which case, it's preferable to determine the jobSize
- * based on chainLog instead. */
- jobLog = MAX(21, params->cParams.chainLog + 4);
+ * based on cycleLog instead. */
+ jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3);
} else {
jobLog = MAX(20, params->cParams.windowLog + 2);
}
@@ -1240,174 +1193,6 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
return (ovLog==0) ? 0 : (size_t)1 << ovLog;
}
-static unsigned
-ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers)
-{
- assert(nbWorkers>0);
- { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
- size_t const jobMaxSize = jobSizeTarget << 2;
- size_t const passSizeMax = jobMaxSize * nbWorkers;
- unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1;
- unsigned const nbJobsLarge = multiplier * nbWorkers;
- unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1;
- unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers);
- return (multiplier>1) ? nbJobsLarge : nbJobsSmall;
-} }
-
-/* ZSTDMT_compress_advanced_internal() :
- * This is a blocking function : it will only give back control to caller after finishing its compression job.
- */
-static size_t
-ZSTDMT_compress_advanced_internal(
- ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_CCtx_params params)
-{
- ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(&params);
- size_t const overlapSize = ZSTDMT_computeOverlapSize(&params);
- unsigned const nbJobs = ZSTDMT_computeNbJobs(&params, srcSize, params.nbWorkers);
- size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
- size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
- const char* const srcStart = (const char*)src;
- size_t remainingSrcSize = srcSize;
- unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */
- size_t frameStartPos = 0, dstBufferPos = 0;
- assert(jobParams.nbWorkers == 0);
- assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
-
- params.jobSize = (U32)avgJobSize;
- DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ",
- nbJobs, (U32)proposedJobSize, (U32)avgJobSize);
-
- if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */
- ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
- DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode");
- if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
- return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams);
- }
-
- assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
- ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
- /* LDM doesn't even try to load the dictionary in single-ingestion mode */
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto))
- return ERROR(memory_allocation);
-
- FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */
-
- { unsigned u;
- for (u=0; u<nbJobs; u++) {
- size_t const jobSize = MIN(remainingSrcSize, avgJobSize);
- size_t const dstBufferCapacity = ZSTD_compressBound(jobSize);
- buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
- buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer;
- size_t dictSize = u ? overlapSize : 0;
-
- mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize;
- mtctx->jobs[u].prefix.size = dictSize;
- mtctx->jobs[u].src.start = srcStart + frameStartPos;
- mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */
- mtctx->jobs[u].consumed = 0;
- mtctx->jobs[u].cSize = 0;
- mtctx->jobs[u].cdict = (u==0) ? cdict : NULL;
- mtctx->jobs[u].fullFrameSize = srcSize;
- mtctx->jobs[u].params = jobParams;
- /* do not calculate checksum within sections, but write it in header for first section */
- mtctx->jobs[u].dstBuff = dstBuffer;
- mtctx->jobs[u].cctxPool = mtctx->cctxPool;
- mtctx->jobs[u].bufPool = mtctx->bufPool;
- mtctx->jobs[u].seqPool = mtctx->seqPool;
- mtctx->jobs[u].serial = &mtctx->serial;
- mtctx->jobs[u].jobID = u;
- mtctx->jobs[u].firstJob = (u==0);
- mtctx->jobs[u].lastJob = (u==nbJobs-1);
-
- DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize);
- DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12);
- POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]);
-
- frameStartPos += jobSize;
- dstBufferPos += dstBufferCapacity;
- remainingSrcSize -= jobSize;
- } }
-
- /* collect result */
- { size_t error = 0, dstPos = 0;
- unsigned jobID;
- for (jobID=0; jobID<nbJobs; jobID++) {
- DEBUGLOG(5, "waiting for job %u ", jobID);
- ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
- while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
- DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID);
- ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
- }
- ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
- DEBUGLOG(5, "ready to write job %u ", jobID);
-
- { size_t const cSize = mtctx->jobs[jobID].cSize;
- if (ZSTD_isError(cSize)) error = cSize;
- if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
- if (jobID) { /* note : job 0 is written directly at dst, which is correct position */
- if (!error)
- memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */
- if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */
- DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst);
- ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
- } }
- mtctx->jobs[jobID].dstBuff = g_nullBuffer;
- mtctx->jobs[jobID].cSize = 0;
- dstPos += cSize ;
- }
- } /* for (jobID=0; jobID<nbJobs; jobID++) */
-
- DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag);
- if (params.fParams.checksumFlag) {
- U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);
- if (dstPos + 4 > dstCapacity) {
- error = ERROR(dstSize_tooSmall);
- } else {
- DEBUGLOG(4, "writing checksum : %08X \n", checksum);
- MEM_writeLE32((char*)dst + dstPos, checksum);
- dstPos += 4;
- } }
-
- if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos);
- return error ? error : dstPos;
- }
-}
-
-size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_parameters params,
- int overlapLog)
-{
- ZSTD_CCtx_params cctxParams = mtctx->params;
- cctxParams.cParams = params.cParams;
- cctxParams.fParams = params.fParams;
- assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX);
- cctxParams.overlapLog = overlapLog;
- return ZSTDMT_compress_advanced_internal(mtctx,
- dst, dstCapacity,
- src, srcSize,
- cdict, cctxParams);
-}
-
-
-size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- int compressionLevel)
-{
- ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
- int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy);
- params.fParams.contentSizeFlag = 1;
- return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog);
-}
-
-
/* ====================================== */
/* ======= Streaming API ======= */
/* ====================================== */
@@ -1432,16 +1217,6 @@ size_t ZSTDMT_initCStream_internal(
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
- mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
- if (mtctx->singleBlockingThread) {
- ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(&params);
- DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode");
- assert(singleThreadParams.nbWorkers == 0);
- return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0],
- dict, dictSize, cdict,
- &singleThreadParams, pledgedSrcSize);
- }
-
DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers);
if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */
@@ -1475,9 +1250,8 @@ size_t ZSTDMT_initCStream_internal(
if (params.rsyncable) {
/* Aim for the targetsectionSize as the average job size. */
- U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
- U32 const rsyncBits = ZSTD_highbit32(jobSizeMB) + 20;
- assert(jobSizeMB >= 1);
+ U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);
+ U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);
DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
mtctx->rsync.hash = 0;
mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
@@ -1504,8 +1278,8 @@ size_t ZSTDMT_initCStream_internal(
size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;
if (mtctx->roundBuff.capacity < capacity) {
if (mtctx->roundBuff.buffer)
- ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem);
- mtctx->roundBuff.buffer = (BYTE*)ZSTD_malloc(capacity, mtctx->cMem);
+ ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
+ mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem);
if (mtctx->roundBuff.buffer == NULL) {
mtctx->roundBuff.capacity = 0;
return ERROR(memory_allocation);
@@ -1530,53 +1304,6 @@ size_t ZSTDMT_initCStream_internal(
return 0;
}
-size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
- const void* dict, size_t dictSize,
- ZSTD_parameters params,
- unsigned long long pledgedSrcSize)
-{
- ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
- DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
- cctxParams.cParams = params.cParams;
- cctxParams.fParams = params.fParams;
- return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL,
- cctxParams, pledgedSrcSize);
-}
-
-size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
- const ZSTD_CDict* cdict,
- ZSTD_frameParameters fParams,
- unsigned long long pledgedSrcSize)
-{
- ZSTD_CCtx_params cctxParams = mtctx->params;
- if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
- cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
- cctxParams.fParams = fParams;
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict,
- cctxParams, pledgedSrcSize);
-}
-
-
-/* ZSTDMT_resetCStream() :
- * pledgedSrcSize can be zero == unknown (for the time being)
- * prefer using ZSTD_CONTENTSIZE_UNKNOWN,
- * as `0` might mean "empty" in the future */
-size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize)
-{
- if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params,
- pledgedSrcSize);
-}
-
-size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
- ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
- ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
- DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel);
- cctxParams.cParams = params.cParams;
- cctxParams.fParams = params.fParams;
- return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
-}
-
/* ZSTDMT_writeLastEmptyBlock()
* Write a single empty block with an end-of-frame to finish a frame.
@@ -1740,7 +1467,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
assert(cSize >= mtctx->jobs[wJobID].dstFlushed);
assert(mtctx->jobs[wJobID].dstBuff.start != NULL);
if (toFlush > 0) {
- memcpy((char*)output->dst + output->pos,
+ ZSTD_memcpy((char*)output->dst + output->pos,
(const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
toFlush);
}
@@ -1894,7 +1621,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
return 0;
}
ZSTDMT_waitForLdmComplete(mtctx, buffer);
- memmove(start, mtctx->inBuff.prefix.start, prefixSize);
+ ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);
mtctx->inBuff.prefix.start = start;
mtctx->roundBuff.pos = prefixSize;
}
@@ -1968,6 +1695,16 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
pos = 0;
prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
+ if ((hash & hitMask) == hitMask) {
+ /* We're already at a sync point so don't load any more until
+ * we're able to flush this sync point.
+ * This likely happened because the job table was full so we
+ * couldn't add our job.
+ */
+ syncPoint.toLoad = 0;
+ syncPoint.flush = 1;
+ return syncPoint;
+ }
} else {
/* We don't have enough bytes buffered to initialize the hash, but
* we know we have at least RSYNC_LENGTH bytes total.
@@ -2022,34 +1759,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
assert(output->pos <= output->size);
assert(input->pos <= input->size);
- if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
- return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
- }
-
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
/* current frame being ended. Only flush/end are allowed */
return ERROR(stage_wrong);
}
- /* single-pass shortcut (note : synchronous-mode) */
- if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */
- && (mtctx->nextJobID == 0) /* just started */
- && (mtctx->inBuff.filled == 0) /* nothing buffered */
- && (!mtctx->jobReady) /* no job already created */
- && (endOp == ZSTD_e_end) /* end order */
- && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */
- size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
- (char*)output->dst + output->pos, output->size - output->pos,
- (const char*)input->src + input->pos, input->size - input->pos,
- mtctx->cdict, mtctx->params);
- if (ZSTD_isError(cSize)) return cSize;
- input->pos = input->size;
- output->pos += cSize;
- mtctx->allJobsCompleted = 1;
- mtctx->frameEnded = 1;
- return 0;
- }
-
/* fill input buffer */
if ( (!mtctx->jobReady)
&& (input->size > input->pos) ) { /* support NULL input */
@@ -2072,13 +1786,21 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);
DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u",
(U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
- memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
+ ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
input->pos += syncPoint.toLoad;
mtctx->inBuff.filled += syncPoint.toLoad;
forwardInputProgress = syncPoint.toLoad>0;
}
- if ((input->pos < input->size) && (endOp == ZSTD_e_end))
- endOp = ZSTD_e_flush; /* can't end now : not all input consumed */
+ }
+ if ((input->pos < input->size) && (endOp == ZSTD_e_end)) {
+ /* Can't end yet because the input is not fully consumed.
+ * We are in one of these cases:
+ * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job.
+ * - We filled the input buffer: flush this job but don't end the frame.
+ * - We hit a synchronization point: flush this job but don't end the frame.
+ */
+ assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable);
+ endOp = ZSTD_e_flush;
}
if ( (mtctx->jobReady)
@@ -2097,47 +1819,3 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
return remainingToFlush;
}
}
-
-
-size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
-{
- FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , "");
-
- /* recommended next input size : fill current input buffer */
- return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
-}
-
-
-static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame)
-{
- size_t const srcSize = mtctx->inBuff.filled;
- DEBUGLOG(5, "ZSTDMT_flushStream_internal");
-
- if ( mtctx->jobReady /* one job ready for a worker to pick up */
- || (srcSize > 0) /* still some data within input buffer */
- || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
- DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
- (U32)srcSize, (U32)endFrame);
- FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , "");
- }
-
- /* check if there is any data available to flush */
- return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame);
-}
-
-
-size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
-{
- DEBUGLOG(5, "ZSTDMT_flushStream");
- if (mtctx->singleBlockingThread)
- return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output);
- return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush);
-}
-
-size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
-{
- DEBUGLOG(4, "ZSTDMT_endStream");
- if (mtctx->singleBlockingThread)
- return ZSTD_endStream(mtctx->cctxPool->cctx[0], output);
- return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end);
-}
diff --git a/Utilities/cmzstd/lib/compress/zstdmt_compress.h b/Utilities/cmzstd/lib/compress/zstdmt_compress.h
index 89914eb7f..2fee2ec74 100644
--- a/Utilities/cmzstd/lib/compress/zstdmt_compress.h
+++ b/Utilities/cmzstd/lib/compress/zstdmt_compress.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -19,113 +19,57 @@
/* Note : This is an internal API.
* These APIs used to be exposed with ZSTDLIB_API,
* because it used to be the only way to invoke MT compression.
- * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2()
- * instead.
- *
- * If you depend on these APIs and can't switch, then define
- * ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library.
- * However, we may completely remove these functions in a future
- * release, so please switch soon.
+ * Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead.
*
* This API requires ZSTD_MULTITHREAD to be defined during compilation,
* otherwise ZSTDMT_createCCtx*() will fail.
*/
-#ifdef ZSTD_LEGACY_MULTITHREADED_API
-# define ZSTDMT_API ZSTDLIB_API
-#else
-# define ZSTDMT_API
-#endif
-
/* === Dependencies === */
-#include <stddef.h> /* size_t */
+#include "../common/zstd_deps.h" /* size_t */
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */
#include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
/* === Constants === */
-#ifndef ZSTDMT_NBWORKERS_MAX
-# define ZSTDMT_NBWORKERS_MAX 200
+#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */
+# define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256)
#endif
-#ifndef ZSTDMT_JOBSIZE_MIN
-# define ZSTDMT_JOBSIZE_MIN (1 MB)
+#ifndef ZSTDMT_JOBSIZE_MIN /* a different value can be selected at compile time */
+# define ZSTDMT_JOBSIZE_MIN (512 KB)
#endif
#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
+/* ========================================================
+ * === Private interface, for use by ZSTD_compress.c ===
+ * === Not exposed in libzstd. Never invoke directly ===
+ * ======================================================== */
+
/* === Memory management === */
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
-ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers);
-/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */
-ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
- ZSTD_customMem cMem);
-ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
-
-ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
-
-
-/* === Simple one-pass compression function === */
-
-ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- int compressionLevel);
-
+ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,
+ ZSTD_customMem cMem,
+ ZSTD_threadPool *pool);
+size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
+size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
/* === Streaming functions === */
-ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel);
-ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */
-
-ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
-ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-
-ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
-ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */
-
-
-/* === Advanced functions and parameters === */
-
-ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- const ZSTD_CDict* cdict,
- ZSTD_parameters params,
- int overlapLog);
-
-ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
- const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
- ZSTD_parameters params,
- unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
-
-ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
- const ZSTD_CDict* cdict,
- ZSTD_frameParameters fparams,
- unsigned long long pledgedSrcSize); /* note : zero means empty */
-
-/* ZSTDMT_parameter :
- * List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
-typedef enum {
- ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */
- ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */
- ZSTDMT_p_rsyncable /* Enables rsyncable mode. */
-} ZSTDMT_parameter;
-
-/* ZSTDMT_setMTCtxParameter() :
- * allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter.
- * The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__
- * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions.
- * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
-ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value);
-
-/* ZSTDMT_getMTCtxParameter() :
- * Query the ZSTDMT_CCtx for a parameter value.
- * @return : 0, or an error code (which can be tested using ZSTD_isError()) */
-ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value);
+size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
+/*! ZSTDMT_initCStream_internal() :
+ * Private use only. Init streaming operation.
+ * expects params to be valid.
+ * must receive dict, or cdict, or none, but not both.
+ * @return : 0, or an error code */
+size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
+ const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
+ const ZSTD_CDict* cdict,
+ ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
/*! ZSTDMT_compressStream_generic() :
* Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream()
@@ -134,16 +78,10 @@ ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter
* 0 if fully flushed
* or an error code
* note : needs to be init using any ZSTD_initCStream*() variant */
-ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
- ZSTD_outBuffer* output,
- ZSTD_inBuffer* input,
- ZSTD_EndDirective endOp);
-
-
-/* ========================================================
- * === Private interface, for use by ZSTD_compress.c ===
- * === Not exposed in libzstd. Never invoke directly ===
- * ======================================================== */
+size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input,
+ ZSTD_EndDirective endOp);
/*! ZSTDMT_toFlushNow()
* Tell how many bytes are ready to be flushed immediately.
@@ -153,15 +91,6 @@ ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
* therefore flushing is limited by speed of oldest job. */
size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx);
-/*! ZSTDMT_CCtxParam_setMTCtxParameter()
- * like ZSTDMT_setMTCtxParameter(), but into a ZSTD_CCtx_Params */
-size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, int value);
-
-/*! ZSTDMT_CCtxParam_setNbWorkers()
- * Set nbWorkers, and clamp it.
- * Also reset jobSize and overlapLog */
-size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers);
-
/*! ZSTDMT_updateCParams_whileCompressing() :
* Updates only a selected set of compression parameters, to remain compatible with current frame.
* New parameters will be applied to next compression job. */
@@ -174,17 +103,6 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);
-/*! ZSTDMT_initCStream_internal() :
- * Private use only. Init streaming operation.
- * expects params to be valid.
- * must receive dict, or cdict, or none, but not both.
- * @return : 0, or an error code */
-size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
- const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
- const ZSTD_CDict* cdict,
- ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
-
-
#if defined (__cplusplus)
}
#endif
diff --git a/Utilities/cmzstd/lib/decompress/huf_decompress.c b/Utilities/cmzstd/lib/decompress/huf_decompress.c
index 68293a130..b93c9a003 100644
--- a/Utilities/cmzstd/lib/decompress/huf_decompress.c
+++ b/Utilities/cmzstd/lib/decompress/huf_decompress.c
@@ -1,7 +1,7 @@
/* ******************************************************************
* huff0 huffman decoder,
* part of Finite State Entropy library
- * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
*
* You can contact the author at :
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
@@ -15,7 +15,7 @@
/* **************************************************************
* Dependencies
****************************************************************/
-#include <string.h> /* memcpy, memset */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */
#include "../common/compiler.h"
#include "../common/bitstream.h" /* BIT_* */
#include "../common/fse.h" /* to compress headers */
@@ -103,7 +103,7 @@ typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved;
static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
{
DTableDesc dtd;
- memcpy(&dtd, table, sizeof(dtd));
+ ZSTD_memcpy(&dtd, table, sizeof(dtd));
return dtd;
}
@@ -115,29 +115,51 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
/*-***************************/
typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */
+/**
+ * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at
+ * a time.
+ */
+static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
+ U64 D4;
+ if (MEM_isLittleEndian()) {
+ D4 = symbol + (nbBits << 8);
+ } else {
+ D4 = (symbol << 8) + nbBits;
+ }
+ D4 *= 0x0001000100010001ULL;
+ return D4;
+}
+
+typedef struct {
+ U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];
+ U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];
+ U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+ BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];
+ BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
+} HUF_ReadDTableX1_Workspace;
+
+
size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
{
+ return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
U32 tableLog = 0;
U32 nbSymbols = 0;
size_t iSize;
void* const dtPtr = DTable + 1;
HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
+ HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;
- U32* rankVal;
- BYTE* huffWeight;
- size_t spaceUsed32 = 0;
-
- rankVal = (U32 *)workSpace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
- huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32);
- spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
+ DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));
+ if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);
DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
- /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
+ /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
- iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);
+ iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2);
if (HUF_isError(iSize)) return iSize;
/* Table header */
@@ -145,52 +167,117 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize
if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
dtd.tableType = 0;
dtd.tableLog = (BYTE)tableLog;
- memcpy(DTable, &dtd, sizeof(dtd));
+ ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
}
- /* Calculate starting value for each rank */
- { U32 n, nextRankStart = 0;
- for (n=1; n<tableLog+1; n++) {
- U32 const current = nextRankStart;
- nextRankStart += (rankVal[n] << (n-1));
- rankVal[n] = current;
- } }
+ /* Compute symbols and rankStart given rankVal:
+ *
+ * rankVal already contains the number of values of each weight.
+ *
+ * symbols contains the symbols ordered by weight. First are the rankVal[0]
+ * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.
+ * symbols[0] is filled (but unused) to avoid a branch.
+ *
+ * rankStart contains the offset where each rank belongs in the DTable.
+ * rankStart[0] is not filled because there are no entries in the table for
+ * weight 0.
+ */
+ {
+ int n;
+ int nextRankStart = 0;
+ int const unroll = 4;
+ int const nLimit = (int)nbSymbols - unroll + 1;
+ for (n=0; n<(int)tableLog+1; n++) {
+ U32 const curr = nextRankStart;
+ nextRankStart += wksp->rankVal[n];
+ wksp->rankStart[n] = curr;
+ }
+ for (n=0; n < nLimit; n += unroll) {
+ int u;
+ for (u=0; u < unroll; ++u) {
+ size_t const w = wksp->huffWeight[n+u];
+ wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);
+ }
+ }
+ for (; n < (int)nbSymbols; ++n) {
+ size_t const w = wksp->huffWeight[n];
+ wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;
+ }
+ }
- /* fill DTable */
- { U32 n;
- size_t const nEnd = nbSymbols;
- for (n=0; n<nEnd; n++) {
- size_t const w = huffWeight[n];
- size_t const length = (1 << w) >> 1;
- size_t const uStart = rankVal[w];
- size_t const uEnd = uStart + length;
- size_t u;
- HUF_DEltX1 D;
- D.byte = (BYTE)n;
- D.nbBits = (BYTE)(tableLog + 1 - w);
- rankVal[w] = (U32)uEnd;
- if (length < 4) {
- /* Use length in the loop bound so the compiler knows it is short. */
- for (u = 0; u < length; ++u)
- dt[uStart + u] = D;
- } else {
- /* Unroll the loop 4 times, we know it is a power of 2. */
- for (u = uStart; u < uEnd; u += 4) {
- dt[u + 0] = D;
- dt[u + 1] = D;
- dt[u + 2] = D;
- dt[u + 3] = D;
- } } } }
+ /* fill DTable
+ * We fill all entries of each weight in order.
+ * That way length is a constant for each iteration of the outter loop.
+ * We can switch based on the length to a different inner loop which is
+ * optimized for that particular case.
+ */
+ {
+ U32 w;
+ int symbol=wksp->rankVal[0];
+ int rankStart=0;
+ for (w=1; w<tableLog+1; ++w) {
+ int const symbolCount = wksp->rankVal[w];
+ int const length = (1 << w) >> 1;
+ int uStart = rankStart;
+ BYTE const nbBits = (BYTE)(tableLog + 1 - w);
+ int s;
+ int u;
+ switch (length) {
+ case 1:
+ for (s=0; s<symbolCount; ++s) {
+ HUF_DEltX1 D;
+ D.byte = wksp->symbols[symbol + s];
+ D.nbBits = nbBits;
+ dt[uStart] = D;
+ uStart += 1;
+ }
+ break;
+ case 2:
+ for (s=0; s<symbolCount; ++s) {
+ HUF_DEltX1 D;
+ D.byte = wksp->symbols[symbol + s];
+ D.nbBits = nbBits;
+ dt[uStart+0] = D;
+ dt[uStart+1] = D;
+ uStart += 2;
+ }
+ break;
+ case 4:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ MEM_write64(dt + uStart, D4);
+ uStart += 4;
+ }
+ break;
+ case 8:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ MEM_write64(dt + uStart, D4);
+ MEM_write64(dt + uStart + 4, D4);
+ uStart += 8;
+ }
+ break;
+ default:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ for (u=0; u < length; u += 16) {
+ MEM_write64(dt + uStart + u + 0, D4);
+ MEM_write64(dt + uStart + u + 4, D4);
+ MEM_write64(dt + uStart + u + 8, D4);
+ MEM_write64(dt + uStart + u + 12, D4);
+ }
+ assert(u == length);
+ uStart += length;
+ }
+ break;
+ }
+ symbol += symbolCount;
+ rankStart += symbolCount * length;
+ }
+ }
return iSize;
}
-size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_readDTableX1_wksp(DTable, src, srcSize,
- workSpace, sizeof(workSpace));
-}
-
FORCE_INLINE_TEMPLATE BYTE
HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
{
@@ -389,20 +476,6 @@ size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
}
-size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
-size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
-}
-
size_t HUF_decompress4X1_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
@@ -419,8 +492,7 @@ static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize,
- workSpace, wkspSize);
+ size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
@@ -436,18 +508,6 @@ size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
}
-size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
-}
-
#endif /* HUF_FORCE_DECOMPRESS_X2 */
@@ -468,13 +528,15 @@ typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
const U32* rankValOrigin, const int minWeight,
const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
- U32 nbBitsBaseline, U16 baseSeq)
+ U32 nbBitsBaseline, U16 baseSeq, U32* wksp, size_t wkspSize)
{
HUF_DEltX2 DElt;
- U32 rankVal[HUF_TABLELOG_MAX + 1];
+ U32* rankVal = wksp;
+ assert(wkspSize >= HUF_TABLELOG_MAX + 1);
+ (void)wkspSize;
/* get pre-calculated rankVal */
- memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+ ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
/* fill skipped values */
if (minWeight>1) {
@@ -509,14 +571,18 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 co
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
const sortedSymbol_t* sortedList, const U32 sortedListSize,
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
- const U32 nbBitsBaseline)
+ const U32 nbBitsBaseline, U32* wksp, size_t wkspSize)
{
- U32 rankVal[HUF_TABLELOG_MAX + 1];
+ U32* rankVal = wksp;
const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
const U32 minBits = nbBitsBaseline - maxWeight;
U32 s;
- memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+ assert(wkspSize >= HUF_TABLELOG_MAX + 1);
+ wksp += HUF_TABLELOG_MAX + 1;
+ wkspSize -= HUF_TABLELOG_MAX + 1;
+
+ ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
/* fill DTable */
for (s=0; s<sortedListSize; s++) {
@@ -534,7 +600,7 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
rankValOrigin[nbBits], minWeight,
sortedList+sortedRank, sortedListSize-sortedRank,
- nbBitsBaseline, symbol);
+ nbBitsBaseline, symbol, wksp, wkspSize);
} else {
HUF_DEltX2 DElt;
MEM_writeLE16(&(DElt.sequence), symbol);
@@ -548,6 +614,15 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
}
}
+typedef struct {
+ rankValCol_t rankVal[HUF_TABLELOG_MAX];
+ U32 rankStats[HUF_TABLELOG_MAX + 1];
+ U32 rankStart0[HUF_TABLELOG_MAX + 2];
+ sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
+ BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
+ U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+} HUF_ReadDTableX2_Workspace;
+
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
const void* src, size_t srcSize,
void* workSpace, size_t wkspSize)
@@ -560,48 +635,33 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
U32 *rankStart;
- rankValCol_t* rankVal;
- U32* rankStats;
- U32* rankStart0;
- sortedSymbol_t* sortedSymbol;
- BYTE* weightList;
- size_t spaceUsed32 = 0;
-
- rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32);
- spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
- rankStats = (U32 *)workSpace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_MAX + 1;
- rankStart0 = (U32 *)workSpace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_MAX + 2;
- sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t);
- spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
- weightList = (BYTE *)((U32 *)workSpace + spaceUsed32);
- spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
-
- rankStart = rankStart0 + 1;
- memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
+ HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
+
+ if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
+
+ rankStart = wksp->rankStart0 + 1;
+ ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
+ ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
- /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
+ /* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
- iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
+ iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), /* bmi2 */ 0);
if (HUF_isError(iSize)) return iSize;
/* check result */
if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
/* find maxWeight */
- for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
+ for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
/* Get start index of each weight */
{ U32 w, nextRankStart = 0;
for (w=1; w<maxW+1; w++) {
- U32 current = nextRankStart;
- nextRankStart += rankStats[w];
- rankStart[w] = current;
+ U32 curr = nextRankStart;
+ nextRankStart += wksp->rankStats[w];
+ rankStart[w] = curr;
}
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
sizeOfSort = nextRankStart;
@@ -610,57 +670,51 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
/* sort symbols by weight */
{ U32 s;
for (s=0; s<nbSymbols; s++) {
- U32 const w = weightList[s];
+ U32 const w = wksp->weightList[s];
U32 const r = rankStart[w]++;
- sortedSymbol[r].symbol = (BYTE)s;
- sortedSymbol[r].weight = (BYTE)w;
+ wksp->sortedSymbol[r].symbol = (BYTE)s;
+ wksp->sortedSymbol[r].weight = (BYTE)w;
}
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
}
/* Build rankVal */
- { U32* const rankVal0 = rankVal[0];
+ { U32* const rankVal0 = wksp->rankVal[0];
{ int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
U32 nextRankVal = 0;
U32 w;
for (w=1; w<maxW+1; w++) {
- U32 current = nextRankVal;
- nextRankVal += rankStats[w] << (w+rescale);
- rankVal0[w] = current;
+ U32 curr = nextRankVal;
+ nextRankVal += wksp->rankStats[w] << (w+rescale);
+ rankVal0[w] = curr;
} }
{ U32 const minBits = tableLog+1 - maxW;
U32 consumed;
for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
- U32* const rankValPtr = rankVal[consumed];
+ U32* const rankValPtr = wksp->rankVal[consumed];
U32 w;
for (w = 1; w < maxW+1; w++) {
rankValPtr[w] = rankVal0[w] >> consumed;
} } } }
HUF_fillDTableX2(dt, maxTableLog,
- sortedSymbol, sizeOfSort,
- rankStart0, rankVal, maxW,
- tableLog+1);
+ wksp->sortedSymbol, sizeOfSort,
+ wksp->rankStart0, wksp->rankVal, maxW,
+ tableLog+1,
+ wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32));
dtd.tableLog = (BYTE)maxTableLog;
dtd.tableType = 1;
- memcpy(DTable, &dtd, sizeof(dtd));
+ ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
return iSize;
}
-size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_readDTableX2_wksp(DTable, src, srcSize,
- workSpace, sizeof(workSpace));
-}
-
FORCE_INLINE_TEMPLATE U32
HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 2);
+ ZSTD_memcpy(op, dt+val, 2);
BIT_skipBits(DStream, dt[val].nbBits);
return dt[val].length;
}
@@ -669,7 +723,7 @@ FORCE_INLINE_TEMPLATE U32
HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt+val, 1);
+ ZSTD_memcpy(op, dt+val, 1);
if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
else {
if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
@@ -890,20 +944,6 @@ size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
}
-size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
-size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
-}
-
size_t HUF_decompress4X2_usingDTable(
void* dst, size_t dstSize,
const void* cSrc, size_t cSrcSize,
@@ -937,20 +977,6 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
}
-size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
-size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
- return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
-}
-
#endif /* HUF_FORCE_DECOMPRESS_X1 */
@@ -1051,67 +1077,6 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
}
-typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
-
-size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
-#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
- static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };
-#endif
-
- /* validation checks */
- if (dstSize == 0) return ERROR(dstSize_tooSmall);
- if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
- if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
- if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
-
- { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
- (void)algoNb;
- assert(algoNb == 0);
- return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
- (void)algoNb;
- assert(algoNb == 1);
- return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);
-#else
- return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
-#endif
- }
-}
-
-size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- /* validation checks */
- if (dstSize == 0) return ERROR(dstSize_tooSmall);
- if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
- if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
- if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
-
- { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
- (void)algoNb;
- assert(algoNb == 0);
- return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
- (void)algoNb;
- assert(algoNb == 1);
- return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
-#else
- return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
- HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
-#endif
- }
-}
-
-size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
-
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
size_t dstSize, const void* cSrc,
size_t cSrcSize, void* workSpace,
@@ -1145,8 +1110,8 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
/* validation checks */
if (dstSize == 0) return ERROR(dstSize_tooSmall);
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
- if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
- if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
+ if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
+ if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
#if defined(HUF_FORCE_DECOMPRESS_X1)
@@ -1168,14 +1133,6 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
}
}
-size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
- const void* cSrc, size_t cSrcSize)
-{
- U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
- return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
- workSpace, sizeof(workSpace));
-}
-
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
{
@@ -1199,7 +1156,7 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS
{
const BYTE* ip = (const BYTE*) cSrc;
- size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);
+ size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
if (HUF_isError(hSize)) return hSize;
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
ip += hSize; cSrcSize -= hSize;
@@ -1246,3 +1203,149 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds
#endif
}
}
+
+#ifndef ZSTD_NO_UNUSED_FUNCTIONS
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_readDTableX1_wksp(DTable, src, srcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
+}
+#endif
+
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_readDTableX2_wksp(DTable, src, srcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+}
+#endif
+
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+}
+#endif
+
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
+ return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
+}
+#endif
+
+typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
+
+size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
+ static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };
+#endif
+
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
+ if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
+ if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);
+#else
+ return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
+#endif
+ }
+}
+
+size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
+ if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
+ if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
+ HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
+#endif
+ }
+}
+
+size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+
+size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize)
+{
+ U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
+ return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
+ workSpace, sizeof(workSpace));
+}
+#endif
diff --git a/Utilities/cmzstd/lib/decompress/zstd_ddict.c b/Utilities/cmzstd/lib/decompress/zstd_ddict.c
index c8cb8ecc9..ce335477b 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_ddict.c
+++ b/Utilities/cmzstd/lib/decompress/zstd_ddict.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -14,7 +14,7 @@
/*-*******************************************************
* Dependencies
*********************************************************/
-#include <string.h> /* memcpy, memmove, memset */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
#include "../common/cpu.h" /* bmi2 */
#include "../common/mem.h" /* low level memory routines */
#define FSE_STATIC_LINKING_ONLY
@@ -127,11 +127,11 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
ddict->dictContent = dict;
if (!dict) dictSize = 0;
} else {
- void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
+ void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);
ddict->dictBuffer = internalBuffer;
ddict->dictContent = internalBuffer;
if (!internalBuffer) return ERROR(memory_allocation);
- memcpy(internalBuffer, dict, dictSize);
+ ZSTD_memcpy(internalBuffer, dict, dictSize);
}
ddict->dictSize = dictSize;
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
@@ -147,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
ZSTD_dictContentType_e dictContentType,
ZSTD_customMem customMem)
{
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
- { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
+ { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);
if (ddict == NULL) return NULL;
ddict->cMem = customMem;
{ size_t const initResult = ZSTD_initDDict_internal(ddict,
@@ -198,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict(
if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
if (sBufferSize < neededSpace) return NULL;
if (dictLoadMethod == ZSTD_dlm_byCopy) {
- memcpy(ddict+1, dict, dictSize); /* local copy */
+ ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */
dict = ddict+1;
}
if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
@@ -213,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
{
if (ddict==NULL) return 0; /* support free on NULL */
{ ZSTD_customMem const cMem = ddict->cMem;
- ZSTD_free(ddict->dictBuffer, cMem);
- ZSTD_free(ddict, cMem);
+ ZSTD_customFree(ddict->dictBuffer, cMem);
+ ZSTD_customFree(ddict, cMem);
return 0;
}
}
diff --git a/Utilities/cmzstd/lib/decompress/zstd_ddict.h b/Utilities/cmzstd/lib/decompress/zstd_ddict.h
index af307efd3..bd03268b5 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_ddict.h
+++ b/Utilities/cmzstd/lib/decompress/zstd_ddict.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -15,7 +15,7 @@
/*-*******************************************************
* Dependencies
*********************************************************/
-#include <stddef.h> /* size_t */
+#include "../common/zstd_deps.h" /* size_t */
#include "../zstd.h" /* ZSTD_DDict, and several public functions */
diff --git a/Utilities/cmzstd/lib/decompress/zstd_decompress.c b/Utilities/cmzstd/lib/decompress/zstd_decompress.c
index be5c7cfc3..910bc034c 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_decompress.c
+++ b/Utilities/cmzstd/lib/decompress/zstd_decompress.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -55,13 +55,14 @@
/*-*******************************************************
* Dependencies
*********************************************************/
-#include <string.h> /* memcpy, memmove, memset */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
#include "../common/cpu.h" /* bmi2 */
#include "../common/mem.h" /* low level memory routines */
#define FSE_STATIC_LINKING_ONLY
#include "../common/fse.h"
#define HUF_STATIC_LINKING_ONLY
#include "../common/huf.h"
+#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
#include "../common/zstd_internal.h" /* blockProperties_t */
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
@@ -72,6 +73,144 @@
#endif
+
+/*************************************
+ * Multiple DDicts Hashset internals *
+ *************************************/
+
+#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
+#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
+ * Currently, that means a 0.75 load factor.
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
+ * the load factor of the ddict hash set.
+ */
+
+#define DDICT_HASHSET_TABLE_BASE_SIZE 64
+#define DDICT_HASHSET_RESIZE_FACTOR 2
+
+/* Hash function to determine starting position of dict insertion within the table
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
+ */
+static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
+ const U64 hash = XXH64(&dictID, sizeof(U32), 0);
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
+ return hash & (hashSet->ddictPtrTableSize - 1);
+}
+
+/* Adds DDict to a hashset without resizing it.
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
+ * Returns 0 if successful, or a zstd error code if something went wrong.
+ */
+static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
+ while (hashSet->ddictPtrTable[idx] != NULL) {
+ /* Replace existing ddict if inserting ddict with same dictID */
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
+ hashSet->ddictPtrTable[idx] = ddict;
+ return 0;
+ }
+ idx &= idxRangeMask;
+ idx++;
+ }
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
+ hashSet->ddictPtrTable[idx] = ddict;
+ hashSet->ddictPtrCount++;
+ return 0;
+}
+
+/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
+ * rehashes all values, allocates new table, frees old table.
+ * Returns 0 on success, otherwise a zstd error code.
+ */
+static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
+ size_t i;
+
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
+ hashSet->ddictPtrTable = newTable;
+ hashSet->ddictPtrTableSize = newTableSize;
+ hashSet->ddictPtrCount = 0;
+ for (i = 0; i < oldTableSize; ++i) {
+ if (oldTable[i] != NULL) {
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
+ }
+ }
+ ZSTD_customFree((void*)oldTable, customMem);
+ DEBUGLOG(4, "Finished re-hash");
+ return 0;
+}
+
+/* Fetches a DDict with the given dictID
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
+ */
+static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
+ for (;;) {
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
+ if (currDictID == dictID || currDictID == 0) {
+ /* currDictID == 0 implies a NULL ddict entry */
+ break;
+ } else {
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
+ idx++;
+ }
+ }
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
+ return hashSet->ddictPtrTable[idx];
+}
+
+/* Allocates space for and returns a ddict hash set
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
+ * Returns NULL if allocation failed.
+ */
+static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
+ DEBUGLOG(4, "Allocating new hash set");
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
+ ret->ddictPtrCount = 0;
+ if (!ret || !ret->ddictPtrTable) {
+ return NULL;
+ }
+ return ret;
+}
+
+/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
+ * Note: The ZSTD_DDict* within the table are NOT freed.
+ */
+static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
+ DEBUGLOG(4, "Freeing ddict hash set");
+ if (hashSet && hashSet->ddictPtrTable) {
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
+ }
+ if (hashSet) {
+ ZSTD_customFree(hashSet, customMem);
+ }
+}
+
+/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
+ * Returns 0 on success, or a ZSTD error.
+ */
+static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
+ }
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
+ return 0;
+}
+
/*-*************************************************************
* Context management
***************************************************************/
@@ -94,11 +233,19 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format)
return startingInputLength;
}
+static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
+{
+ assert(dctx->streamStage == zdss_init);
+ dctx->format = ZSTD_f_zstd1;
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+ dctx->outBufferMode = ZSTD_bm_buffered;
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
+}
+
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
{
- dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */
dctx->staticSize = 0;
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
dctx->ddict = NULL;
dctx->ddictLocal = NULL;
dctx->dictEnd = NULL;
@@ -113,7 +260,8 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->noForwardProgress = 0;
dctx->oversizedDuration = 0;
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
- dctx->outBufferMode = ZSTD_obm_buffered;
+ dctx->ddictSet = NULL;
+ ZSTD_DCtx_resetParameters(dctx);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
dctx->dictContentEndForFuzzing = NULL;
#endif
@@ -134,9 +282,9 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
{
- if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
- { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
if (!dctx) return NULL;
dctx->customMem = customMem;
ZSTD_initDCtx_internal(dctx);
@@ -164,13 +312,17 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
{ ZSTD_customMem const cMem = dctx->customMem;
ZSTD_clearDict(dctx);
- ZSTD_free(dctx->inBuff, cMem);
+ ZSTD_customFree(dctx->inBuff, cMem);
dctx->inBuff = NULL;
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (dctx->legacyContext)
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
#endif
- ZSTD_free(dctx, cMem);
+ if (dctx->ddictSet) {
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
+ dctx->ddictSet = NULL;
+ }
+ ZSTD_customFree(dctx, cMem);
return 0;
}
}
@@ -179,7 +331,30 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
{
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
- memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
+}
+
+/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
+ * accordingly sets the ddict to be used to decompress the frame.
+ *
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
+ *
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
+ */
+static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
+ if (dctx->ddict) {
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
+ if (frameDDict) {
+ DEBUGLOG(4, "DDict found!");
+ ZSTD_clearDict(dctx);
+ dctx->dictID = dctx->fParams.dictID;
+ dctx->ddict = frameDDict;
+ dctx->dictUses = ZSTD_use_indefinitely;
+ }
+ }
}
@@ -246,7 +421,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
const BYTE* ip = (const BYTE*)src;
size_t const minInputSize = ZSTD_startingInputLength(format);
- memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
if (srcSize < minInputSize) return minInputSize;
RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
@@ -256,7 +431,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
/* skippable frame */
if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
- memset(zfhPtr, 0, sizeof(*zfhPtr));
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
zfhPtr->frameType = ZSTD_skippableFrame;
return 0;
@@ -433,12 +608,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
/** ZSTD_decodeFrameHeader() :
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
{
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
if (ZSTD_isError(result)) return result; /* invalid header */
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
+
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
+ ZSTD_DCtx_selectFrameDDict(dctx);
+ }
+
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* Skip the dictID check in fuzzing mode, because it makes the search
* harder.
@@ -446,7 +628,9 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
dictionary_wrong, "");
#endif
- if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
+ if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
+ dctx->processedCSize += headerSize;
return 0;
}
@@ -461,7 +645,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
{
ZSTD_frameSizeInfo frameSizeInfo;
- memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
if (ZSTD_isLegacy(src, srcSize))
@@ -516,7 +700,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
ip += 4;
}
- frameSizeInfo.compressedSize = ip - ipstart;
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
? zfh.frameContentSize
: nbBlocks * zfh.blockSizeMax;
@@ -569,7 +753,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
{
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
- ZSTD_checkContinuity(dctx, blockStart);
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
dctx->previousDstEnd = (const char*)blockStart + blockSize;
return blockSize;
}
@@ -579,12 +763,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
DEBUGLOG(5, "ZSTD_copyRawBlock");
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
if (dst == NULL) {
if (srcSize == 0) return 0;
RETURN_ERROR(dstBuffer_null, "");
}
- RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
- memcpy(dst, src, srcSize);
+ ZSTD_memcpy(dst, src, srcSize);
return srcSize;
}
@@ -592,15 +776,41 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
BYTE b,
size_t regenSize)
{
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
if (dst == NULL) {
if (regenSize == 0) return 0;
RETURN_ERROR(dstBuffer_null, "");
}
- RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
- memset(dst, b, regenSize);
+ ZSTD_memset(dst, b, regenSize);
return regenSize;
}
+static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
+{
+#if ZSTD_TRACE
+ if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
+ ZSTD_Trace trace;
+ ZSTD_memset(&trace, 0, sizeof(trace));
+ trace.version = ZSTD_VERSION_NUMBER;
+ trace.streaming = streaming;
+ if (dctx->ddict) {
+ trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
+ trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
+ trace.dictionaryIsCold = dctx->ddictIsCold;
+ }
+ trace.uncompressedSize = (size_t)uncompressedSize;
+ trace.compressedSize = (size_t)compressedSize;
+ trace.dctx = dctx;
+ ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
+ }
+#else
+ (void)dctx;
+ (void)uncompressedSize;
+ (void)compressedSize;
+ (void)streaming;
+#endif
+}
+
/*! ZSTD_decompressFrame() :
* @dctx must be properly initialized
@@ -610,8 +820,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void** srcPtr, size_t *srcSizePtr)
{
- const BYTE* ip = (const BYTE*)(*srcPtr);
- BYTE* const ostart = (BYTE* const)dst;
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
+ const BYTE* ip = istart;
+ BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
BYTE* op = ostart;
size_t remainingSrcSize = *srcSizePtr;
@@ -647,13 +858,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
switch(blockProperties.blockType)
{
case bt_compressed:
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1);
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
break;
case bt_raw :
- decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
break;
case bt_rle :
- decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize);
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
break;
case bt_reserved :
default:
@@ -661,7 +872,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
}
if (ZSTD_isError(decodedSize)) return decodedSize;
- if (dctx->fParams.checksumFlag)
+ if (dctx->validateChecksum)
XXH64_update(&dctx->xxhState, op, decodedSize);
if (decodedSize != 0)
op += decodedSize;
@@ -676,19 +887,21 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
corruption_detected, "");
}
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
- U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
- U32 checkRead;
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
- checkRead = MEM_readLE32(ip);
- RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
+ if (!dctx->forceIgnoreChecksum) {
+ U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
+ U32 checkRead;
+ checkRead = MEM_readLE32(ip);
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
+ }
ip += 4;
remainingSrcSize -= 4;
}
-
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
/* Allow caller to get size read */
*srcPtr = ip;
*srcSizePtr = remainingSrcSize;
- return op-ostart;
+ return (size_t)(op-ostart);
}
static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
@@ -721,7 +934,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
if (ZSTD_isError(decodedSize)) return decodedSize;
- assert(decodedSize <=- dstCapacity);
+ assert(decodedSize <= dstCapacity);
dst = (BYTE*)dst + decodedSize;
dstCapacity -= decodedSize;
@@ -753,7 +966,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
* use this in all cases but ddict */
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
}
- ZSTD_checkContinuity(dctx, dst);
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
&src, &srcSize);
@@ -761,15 +974,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
(ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
&& (moreThan1Frame==1),
srcSize_wrong,
- "at least one frame successfully completed, but following "
- "bytes are garbage: it's more likely to be a srcSize error, "
- "specifying more bytes than compressed size of frame(s). This "
- "error message replaces ERROR(prefix_unknown), which would be "
- "confusing, as the first header is actually correct. Note that "
- "one could be unlucky, it might be a corruption error instead, "
- "happening right at the place where we expect zstd magic "
- "bytes. But this is _much_ less likely than a srcSize field "
- "error.");
+ "At least one frame successfully completed, "
+ "but following bytes are garbage: "
+ "it's more likely to be a srcSize error, "
+ "specifying more input bytes than size of frame(s). "
+ "Note: one could be unlucky, it might be a corruption error instead, "
+ "happening right at the place where we expect zstd magic bytes. "
+ "But this is _much_ less likely than a srcSize field error.");
if (ZSTD_isError(res)) return res;
assert(res <= dstCapacity);
if (res != 0)
@@ -781,7 +992,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
- return (BYTE*)dst - (BYTE*)dststart;
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
}
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
@@ -890,7 +1101,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
/* Sanity check */
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
- if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
+
+ dctx->processedCSize += srcSize;
switch (dctx->stage)
{
@@ -899,21 +1112,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
if (dctx->format == ZSTD_f_zstd1) { /* allows header */
assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
- memcpy(dctx->headerBuffer, src, srcSize);
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
dctx->stage = ZSTDds_decodeSkippableHeader;
return 0;
} }
dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
- memcpy(dctx->headerBuffer, src, srcSize);
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
dctx->expected = dctx->headerSize - srcSize;
dctx->stage = ZSTDds_decodeFrameHeader;
return 0;
case ZSTDds_decodeFrameHeader:
assert(src != NULL);
- memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
dctx->expected = ZSTD_blockHeaderSize;
dctx->stage = ZSTDds_decodeBlockHeader;
@@ -977,7 +1190,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
dctx->decodedSize += rSize;
- if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
+ if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
dctx->previousDstEnd = (char*)dst + rSize;
/* Stay on the same stage until we are finished streaming the block. */
@@ -995,6 +1208,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
dctx->expected = 4;
dctx->stage = ZSTDds_checkChecksum;
} else {
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
dctx->expected = 0; /* ends here */
dctx->stage = ZSTDds_getFrameHeaderSize;
}
@@ -1007,10 +1221,14 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_checkChecksum:
assert(srcSize == 4); /* guaranteed by dctx->expected */
- { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
- U32 const check32 = MEM_readLE32(src);
- DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
- RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
+ {
+ if (dctx->validateChecksum) {
+ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
+ U32 const check32 = MEM_readLE32(src);
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
+ }
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
dctx->expected = 0;
dctx->stage = ZSTDds_getFrameHeaderSize;
return 0;
@@ -1019,7 +1237,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
case ZSTDds_decodeSkippableHeader:
assert(src != NULL);
assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
- memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
dctx->stage = ZSTDds_skipFrame;
return 0;
@@ -1075,7 +1293,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
workspace, workspaceSize);
#else
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
- dictPtr, dictEnd - dictPtr,
+ dictPtr, (size_t)(dictEnd - dictPtr),
workspace, workspaceSize);
#endif
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
@@ -1084,40 +1302,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
{ short offcodeNCount[MaxOff+1];
unsigned offcodeMaxValue = MaxOff, offcodeLog;
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
ZSTD_buildFSETable( entropy->OFTable,
offcodeNCount, offcodeMaxValue,
OF_base, OF_bits,
- offcodeLog);
+ offcodeLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */0);
dictPtr += offcodeHeaderSize;
}
{ short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog;
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
ZSTD_buildFSETable( entropy->MLTable,
matchlengthNCount, matchlengthMaxValue,
ML_base, ML_bits,
- matchlengthLog);
+ matchlengthLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */ 0);
dictPtr += matchlengthHeaderSize;
}
{ short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog;
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
ZSTD_buildFSETable( entropy->LLTable,
litlengthNCount, litlengthMaxValue,
LL_base, LL_bits,
- litlengthLog);
+ litlengthLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */ 0);
dictPtr += litlengthHeaderSize;
}
@@ -1131,7 +1355,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
entropy->rep[i] = rep;
} }
- return dictPtr - (const BYTE*)dict;
+ return (size_t)(dictPtr - (const BYTE*)dict);
}
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
@@ -1158,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
{
assert(dctx != NULL);
+#if ZSTD_TRACE
+ dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
+#endif
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
dctx->stage = ZSTDds_getFrameHeaderSize;
+ dctx->processedCSize = 0;
dctx->decodedSize = 0;
dctx->previousDstEnd = NULL;
dctx->prefixStart = NULL;
@@ -1170,7 +1398,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
dctx->dictID = 0;
dctx->bType = bt_reserved;
ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
dctx->LLTptr = dctx->entropy.LLTable;
dctx->MLTptr = dctx->entropy.MLTable;
dctx->OFTptr = dctx->entropy.OFTable;
@@ -1373,6 +1601,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
if (ddict) {
dctx->ddict = ddict;
dctx->dictUses = ZSTD_use_indefinitely;
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
+ if (dctx->ddictSet == NULL) {
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
+ if (!dctx->ddictSet) {
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
+ }
+ }
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
+ }
}
return 0;
}
@@ -1394,7 +1632,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
{
- return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format);
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
}
ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
@@ -1411,8 +1649,16 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
return bounds;
case ZSTD_d_stableOutBuffer:
- bounds.lowerBound = (int)ZSTD_obm_buffered;
- bounds.upperBound = (int)ZSTD_obm_stable;
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
+ bounds.upperBound = (int)ZSTD_bm_stable;
+ return bounds;
+ case ZSTD_d_forceIgnoreChecksum:
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
+ return bounds;
+ case ZSTD_d_refMultipleDDicts:
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
return bounds;
default:;
}
@@ -1436,6 +1682,29 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
}
+size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
+{
+ switch (param) {
+ case ZSTD_d_windowLogMax:
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
+ return 0;
+ case ZSTD_d_format:
+ *value = (int)dctx->format;
+ return 0;
+ case ZSTD_d_stableOutBuffer:
+ *value = (int)dctx->outBufferMode;
+ return 0;
+ case ZSTD_d_forceIgnoreChecksum:
+ *value = (int)dctx->forceIgnoreChecksum;
+ return 0;
+ case ZSTD_d_refMultipleDDicts:
+ *value = (int)dctx->refMultipleDDicts;
+ return 0;
+ default:;
+ }
+ RETURN_ERROR(parameter_unsupported, "");
+}
+
size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
{
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
@@ -1451,7 +1720,18 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
return 0;
case ZSTD_d_stableOutBuffer:
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
- dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
+ return 0;
+ case ZSTD_d_forceIgnoreChecksum:
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
+ return 0;
+ case ZSTD_d_refMultipleDDicts:
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
+ if (dctx->staticSize != 0) {
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
+ }
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
return 0;
default:;
}
@@ -1469,8 +1749,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
|| (reset == ZSTD_reset_session_and_parameters) ) {
RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
ZSTD_clearDict(dctx);
- dctx->format = ZSTD_f_zstd1;
- dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+ ZSTD_DCtx_resetParameters(dctx);
}
return 0;
}
@@ -1524,7 +1803,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne
{
if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
zds->oversizedDuration++;
- else
+ else
zds->oversizedDuration = 0;
}
@@ -1538,7 +1817,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
{
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
/* No requirement when ZSTD_obm_stable is not enabled. */
- if (zds->outBufferMode != ZSTD_obm_stable)
+ if (zds->outBufferMode != ZSTD_bm_stable)
return 0;
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
* the context is reset.
@@ -1548,7 +1827,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const*
/* The buffer must match our expectation exactly. */
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
return 0;
- RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
}
/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
@@ -1560,7 +1839,7 @@ static size_t ZSTD_decompressContinueStream(
ZSTD_DStream* zds, char** op, char* oend,
void const* src, size_t srcSize) {
int const isSkipFrame = ZSTD_isSkipFrame(zds);
- if (zds->outBufferMode == ZSTD_obm_buffered) {
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
size_t const decodedSize = ZSTD_decompressContinue(zds,
zds->outBuff + zds->outStart, dstSize, src, srcSize);
@@ -1573,14 +1852,14 @@ static size_t ZSTD_decompressContinueStream(
}
} else {
/* Write directly into the output buffer */
- size_t const dstSize = isSkipFrame ? 0 : oend - *op;
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
FORWARD_IF_ERROR(decodedSize, "");
*op += decodedSize;
/* Flushing is not needed. */
zds->streamStage = zdss_read;
assert(*op <= oend);
- assert(zds->outBufferMode == ZSTD_obm_stable);
+ assert(zds->outBufferMode == ZSTD_bm_stable);
}
return 0;
}
@@ -1635,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
} }
#endif
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
+ if (zds->refMultipleDDicts && zds->ddictSet) {
+ ZSTD_DCtx_selectFrameDDict(zds);
+ }
DEBUGLOG(5, "header size : %u", (U32)hSize);
if (ZSTD_isError(hSize)) {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
@@ -1663,14 +1945,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
assert(iend >= ip);
if (toLoad > remainingInput) { /* not enough input to load full header */
if (remainingInput > 0) {
- memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
zds->lhSize += remainingInput;
}
input->pos = input->size;
return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
}
assert(ip != NULL);
- memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
break;
} }
@@ -1678,10 +1960,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
&& zds->fParams.frameType != ZSTD_skippableFrame
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
if (cSize <= (size_t)(iend-istart)) {
/* shortcut : using single-pass mode */
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds));
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
if (ZSTD_isError(decompressedSize)) return decompressedSize;
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
ip = istart + cSize;
@@ -1693,7 +1975,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
} }
/* Check output buffer is large enough for ZSTD_odm_stable. */
- if (zds->outBufferMode == ZSTD_obm_stable
+ if (zds->outBufferMode == ZSTD_bm_stable
&& zds->fParams.frameType != ZSTD_skippableFrame
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
@@ -1723,7 +2005,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
/* Adapt buffer sizes to frame header instructions */
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
- size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
: 0;
@@ -1731,7 +2013,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
{ int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
-
+
if (tooSmall || tooLarge) {
size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
DEBUGLOG(4, "inBuff : from %u to %u",
@@ -1745,10 +2027,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
memory_allocation, "");
} else {
- ZSTD_free(zds->inBuff, zds->customMem);
+ ZSTD_customFree(zds->inBuff, zds->customMem);
zds->inBuffSize = 0;
zds->outBuffSize = 0;
- zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
}
zds->inBuffSize = neededInBuffSize;
@@ -1760,7 +2042,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
case zdss_read:
DEBUGLOG(5, "stage zdss_read");
- { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip);
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
if (neededInSize==0) { /* end of frame */
zds->streamStage = zdss_init;
@@ -1790,7 +2072,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
corruption_detected,
"should never happen");
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip);
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
}
ip += loadedSize;
zds->inPos += loadedSize;
@@ -1804,7 +2086,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
}
case zdss_flush:
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
- size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
op += flushedSize;
zds->outStart += flushedSize;
if (flushedSize == toFlushSize) { /* flush completed */
diff --git a/Utilities/cmzstd/lib/decompress/zstd_decompress_block.c b/Utilities/cmzstd/lib/decompress/zstd_decompress_block.c
index ad3b3d8db..349dcdc33 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_decompress_block.c
+++ b/Utilities/cmzstd/lib/decompress/zstd_decompress_block.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -14,7 +14,7 @@
/*-*******************************************************
* Dependencies
*********************************************************/
-#include <string.h> /* memcpy, memmove, memset */
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
#include "../common/compiler.h" /* prefetch */
#include "../common/cpu.h" /* bmi2 */
#include "../common/mem.h" /* low level memory routines */
@@ -44,7 +44,7 @@
/*_*******************************************************
* Memory operations
**********************************************************/
-static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
+static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); }
/*-*************************************************************
@@ -166,7 +166,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
dctx->litSize = litSize;
dctx->litEntropy = 1;
if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
return litCSize + lhSize;
}
@@ -191,10 +191,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, "");
- memcpy(dctx->litBuffer, istart+lhSize, litSize);
+ ZSTD_memcpy(dctx->litBuffer, istart+lhSize, litSize);
dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+ ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
return lhSize+litSize;
}
/* direct reference into compressed stream */
@@ -223,7 +223,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
break;
}
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
- memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
+ ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize;
return lhSize+1;
@@ -236,7 +236,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
/* Default FSE distribution tables.
* These are pre-calculated FSE decoding tables using default distributions as defined in specification :
- * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions
+ * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions
* They were generated programmatically with following method :
* - start from default distributions, present in /lib/common/zstd_internal.h
* - generate tables normally, using ZSTD_buildFSETable()
@@ -364,23 +364,26 @@ static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddB
* generate FSE decoding table for one symbol (ll, ml or off)
* cannot fail if input is valid =>
* all inputs are presumed validated at this stage */
-void
-ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+FORCE_INLINE_TEMPLATE
+void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
const U32* baseValue, const U32* nbAdditionalBits,
- unsigned tableLog)
+ unsigned tableLog, void* wksp, size_t wkspSize)
{
ZSTD_seqSymbol* const tableDecode = dt+1;
- U16 symbolNext[MaxSeq+1];
-
U32 const maxSV1 = maxSymbolValue + 1;
U32 const tableSize = 1 << tableLog;
- U32 highThreshold = tableSize-1;
+
+ U16* symbolNext = (U16*)wksp;
+ BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1);
+ U32 highThreshold = tableSize - 1;
+
/* Sanity Checks */
assert(maxSymbolValue <= MaxSeq);
assert(tableLog <= MaxFSELog);
-
+ assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE);
+ (void)wkspSize;
/* Init, lay down lowprob symbols */
{ ZSTD_seqSymbol_header DTableH;
DTableH.tableLog = tableLog;
@@ -396,16 +399,69 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
assert(normalizedCounter[s]>=0);
symbolNext[s] = (U16)normalizedCounter[s];
} } }
- memcpy(dt, &DTableH, sizeof(DTableH));
+ ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
}
/* Spread symbols */
- { U32 const tableMask = tableSize-1;
+ assert(tableSize <= 512);
+ /* Specialized symbol spreading for the case when there are
+ * no low probability (-1 count) symbols. When compressing
+ * small blocks we avoid low probability symbols to hit this
+ * case, since header decoding speed matters more.
+ */
+ if (highThreshold == tableSize - 1) {
+ size_t const tableMask = tableSize-1;
+ size_t const step = FSE_TABLESTEP(tableSize);
+ /* First lay down the symbols in order.
+ * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
+ * misses since small blocks generally have small table logs, so nearly
+ * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
+ * our buffer to handle the over-write.
+ */
+ {
+ U64 const add = 0x0101010101010101ull;
+ size_t pos = 0;
+ U64 sv = 0;
+ U32 s;
+ for (s=0; s<maxSV1; ++s, sv += add) {
+ int i;
+ int const n = normalizedCounter[s];
+ MEM_write64(spread + pos, sv);
+ for (i = 8; i < n; i += 8) {
+ MEM_write64(spread + pos + i, sv);
+ }
+ pos += n;
+ }
+ }
+ /* Now we spread those positions across the table.
+ * The benefit of doing it in two stages is that we avoid the the
+ * variable size inner loop, which caused lots of branch misses.
+ * Now we can run through all the positions without any branch misses.
+ * We unroll the loop twice, since that is what emperically worked best.
+ */
+ {
+ size_t position = 0;
+ size_t s;
+ size_t const unroll = 2;
+ assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
+ for (s = 0; s < (size_t)tableSize; s += unroll) {
+ size_t u;
+ for (u = 0; u < unroll; ++u) {
+ size_t const uPosition = (position + (u * step)) & tableMask;
+ tableDecode[uPosition].baseValue = spread[s + u];
+ }
+ position = (position + (unroll * step)) & tableMask;
+ }
+ assert(position == 0);
+ }
+ } else {
+ U32 const tableMask = tableSize-1;
U32 const step = FSE_TABLESTEP(tableSize);
U32 s, position = 0;
for (s=0; s<maxSV1; s++) {
int i;
- for (i=0; i<normalizedCounter[s]; i++) {
+ int const n = normalizedCounter[s];
+ for (i=0; i<n; i++) {
tableDecode[position].baseValue = s;
position = (position + step) & tableMask;
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
@@ -414,7 +470,8 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
}
/* Build Decoding table */
- { U32 u;
+ {
+ U32 u;
for (u=0; u<tableSize; u++) {
U32 const symbol = tableDecode[u].baseValue;
U32 const nextState = symbolNext[symbol]++;
@@ -423,7 +480,46 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
assert(nbAdditionalBits[symbol] < 255);
tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
tableDecode[u].baseValue = baseValue[symbol];
- } }
+ }
+ }
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize)
+{
+ ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+}
+
+#if DYNAMIC_BMI2
+TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize)
+{
+ ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+}
+#endif
+
+void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U32* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+ return;
+ }
+#endif
+ (void)bmi2;
+ ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
}
@@ -435,7 +531,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
const void* src, size_t srcSize,
const U32* baseValue, const U32* nbAdditionalBits,
const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,
- int ddictIsCold, int nbSeq)
+ int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,
+ int bmi2)
{
switch(type)
{
@@ -467,7 +564,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, "");
RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, "");
- ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog);
+ ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2);
*DTablePtr = DTableSpace;
return headerSize;
}
@@ -480,7 +577,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
const void* src, size_t srcSize)
{
- const BYTE* const istart = (const BYTE* const)src;
+ const BYTE* const istart = (const BYTE*)src;
const BYTE* const iend = istart + srcSize;
const BYTE* ip = istart;
int nbSeq;
@@ -499,7 +596,8 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
if (nbSeq > 0x7F) {
if (nbSeq == 0xFF) {
RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, "");
- nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
+ nbSeq = MEM_readLE16(ip) + LONGNBSEQ;
+ ip+=2;
} else {
RETURN_ERROR_IF(ip >= iend, srcSize_wrong, "");
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
@@ -520,7 +618,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip, iend-ip,
LL_base, LL_bits,
LL_defaultDTable, dctx->fseEntropy,
- dctx->ddictIsCold, nbSeq);
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ dctx->bmi2);
RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += llhSize;
}
@@ -530,7 +630,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip, iend-ip,
OF_base, OF_bits,
OF_defaultDTable, dctx->fseEntropy,
- dctx->ddictIsCold, nbSeq);
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ dctx->bmi2);
RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += ofhSize;
}
@@ -540,7 +642,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ip, iend-ip,
ML_base, ML_bits,
ML_defaultDTable, dctx->fseEntropy,
- dctx->ddictIsCold, nbSeq);
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ dctx->bmi2);
RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += mlhSize;
}
@@ -554,7 +658,6 @@ typedef struct {
size_t litLength;
size_t matchLength;
size_t offset;
- const BYTE* match;
} seq_t;
typedef struct {
@@ -568,9 +671,6 @@ typedef struct {
ZSTD_fseState stateOffb;
ZSTD_fseState stateML;
size_t prevOffset[ZSTD_REP_NUM];
- const BYTE* prefixStart;
- const BYTE* dictEnd;
- size_t pos;
} seqState_t;
/*! ZSTD_overlapCopy8() :
@@ -686,12 +786,12 @@ size_t ZSTD_execSequenceEnd(BYTE* op,
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
match = dictEnd - (prefixStart-match);
if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
+ ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
match = prefixStart;
@@ -752,12 +852,12 @@ size_t ZSTD_execSequence(BYTE* op,
RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, "");
match = dictEnd + (match - prefixStart);
if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
+ ZSTD_memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
match = prefixStart;
@@ -832,10 +932,9 @@ ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD
: 0)
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
-typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e;
FORCE_INLINE_TEMPLATE seq_t
-ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch)
+ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
{
seq_t seq;
ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
@@ -910,14 +1009,6 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
- if (prefetch == ZSTD_p_prefetch) {
- size_t const pos = seqState->pos + seq.litLength;
- const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
- seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
- * No consequence though : no memory access will occur, offset is only used for prefetching */
- seqState->pos = pos + seq.matchLength;
- }
-
/* ANS state update
* gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
* clang-9.2.0 does 7% worse with ZSTD_updateFseState().
@@ -948,7 +1039,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
}
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
+MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
{
size_t const windowSize = dctx->fParams.windowSize;
/* No dictionary used. */
@@ -969,6 +1060,7 @@ MEM_STATIC void ZSTD_assertValidSequence(
seq_t const seq,
BYTE const* prefixStart, BYTE const* virtualStart)
{
+#if DEBUGLEVEL >= 1
size_t const windowSize = dctx->fParams.windowSize;
size_t const sequenceSize = seq.litLength + seq.matchLength;
BYTE const* const oLitEnd = op + seq.litLength;
@@ -986,6 +1078,9 @@ MEM_STATIC void ZSTD_assertValidSequence(
/* Offset must be within our window. */
assert(seq.offset <= windowSize);
}
+#else
+ (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart;
+#endif
}
#endif
@@ -1000,7 +1095,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
- BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + maxDstSize;
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
@@ -1014,7 +1109,6 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
/* Regen sequences */
if (nbSeq) {
seqState_t seqState;
- size_t error = 0;
dctx->fseEntropy = 1;
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
RETURN_ERROR_IF(
@@ -1048,13 +1142,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
* If you see most cycles served out of the DSB you've hit the good case.
* If it is pretty even then you may be in an okay case.
*
- * I've been able to reproduce this issue on the following CPUs:
+ * This issue has been reproduced on the following CPUs:
* - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
* Use Instruments->Counters to get DSB/MITE cycles.
* I never got performance swings, but I was able to
* go from the good case of mostly DSB to half of the
* cycles served from MITE.
* - Coffeelake: Intel i9-9900k
+ * - Coffeelake: Intel i7-9700k
*
* I haven't been able to reproduce the instability or DSB misses on any
* of the following CPUS:
@@ -1067,33 +1162,35 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
*
* https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
*/
+ __asm__(".p2align 6");
+ __asm__("nop");
__asm__(".p2align 5");
__asm__("nop");
+# if __GNUC__ >= 9
+ /* better for gcc-9 and gcc-10, worse for clang and gcc-8 */
+ __asm__(".p2align 3");
+# else
__asm__(".p2align 4");
+# endif
#endif
for ( ; ; ) {
- seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch);
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
assert(!ZSTD_isError(oneSeqSize));
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
BIT_reloadDStream(&(seqState.DStream));
- /* gcc and clang both don't like early returns in this loop.
- * gcc doesn't like early breaks either.
- * Instead save an error and report it at the end.
- * When there is an error, don't increment op, so we don't
- * overwrite.
- */
- if (UNLIKELY(ZSTD_isError(oneSeqSize))) error = oneSeqSize;
- else op += oneSeqSize;
- if (UNLIKELY(!--nbSeq)) break;
}
/* check if reached exact end */
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
- if (ZSTD_isError(error)) return error;
RETURN_ERROR_IF(nbSeq, corruption_detected, "");
RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
/* save reps for next block */
@@ -1104,7 +1201,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
{ size_t const lastLLSize = litEnd - litPtr;
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
if (op != NULL) {
- memcpy(op, litPtr, lastLLSize);
+ ZSTD_memcpy(op, litPtr, lastLLSize);
op += lastLLSize;
}
}
@@ -1124,6 +1221,24 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
+ const BYTE* const prefixStart, const BYTE* const dictEnd)
+{
+ prefetchPos += sequence.litLength;
+ { const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;
+ const BYTE* const match = matchBase + prefetchPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
+ * No consequence though : memory address is only used for prefetching, not for dereferencing */
+ PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ }
+ return prefetchPos + sequence.matchLength;
+}
+
+/* This decoding function employs prefetching
+ * to reduce latency impact of cache misses.
+ * It's generally employed when block contains a significant portion of long-distance matches
+ * or when coupled with a "cold" dictionary */
FORCE_INLINE_TEMPLATE size_t
ZSTD_decompressSequencesLong_body(
ZSTD_DCtx* dctx,
@@ -1134,7 +1249,7 @@ ZSTD_decompressSequencesLong_body(
{
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
- BYTE* const ostart = (BYTE* const)dst;
+ BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + maxDstSize;
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
@@ -1146,18 +1261,17 @@ ZSTD_decompressSequencesLong_body(
/* Regen sequences */
if (nbSeq) {
-#define STORED_SEQS 4
+#define STORED_SEQS 8
#define STORED_SEQS_MASK (STORED_SEQS-1)
-#define ADVANCED_SEQS 4
+#define ADVANCED_SEQS STORED_SEQS
seq_t sequences[STORED_SEQS];
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
seqState_t seqState;
int seqNb;
+ size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */
+
dctx->fseEntropy = 1;
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
- seqState.prefixStart = prefixStart;
- seqState.pos = (size_t)(op-prefixStart);
- seqState.dictEnd = dictEnd;
assert(dst != NULL);
assert(iend >= ip);
RETURN_ERROR_IF(
@@ -1169,21 +1283,23 @@ ZSTD_decompressSequencesLong_body(
/* prepare in advance */
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
- sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
- PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb] = sequence;
}
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
/* decode and decompress */
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
assert(!ZSTD_isError(oneSeqSize));
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
#endif
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
sequences[seqNb & STORED_SEQS_MASK] = sequence;
op += oneSeqSize;
}
@@ -1209,7 +1325,7 @@ ZSTD_decompressSequencesLong_body(
{ size_t const lastLLSize = litEnd - litPtr;
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
if (op != NULL) {
- memcpy(op, litPtr, lastLLSize);
+ ZSTD_memcpy(op, litPtr, lastLLSize);
op += lastLLSize;
}
}
@@ -1409,9 +1525,9 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
}
-void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
{
- if (dst != dctx->previousDstEnd) { /* not contiguous */
+ if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */
dctx->dictEnd = dctx->previousDstEnd;
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
dctx->prefixStart = dst;
@@ -1425,7 +1541,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
const void* src, size_t srcSize)
{
size_t dSize;
- ZSTD_checkContinuity(dctx, dst);
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
dctx->previousDstEnd = (char*)dst + dSize;
return dSize;
diff --git a/Utilities/cmzstd/lib/decompress/zstd_decompress_block.h b/Utilities/cmzstd/lib/decompress/zstd_decompress_block.h
index bf39b7350..049a0cd84 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_decompress_block.h
+++ b/Utilities/cmzstd/lib/decompress/zstd_decompress_block.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -15,7 +15,7 @@
/*-*******************************************************
* Dependencies
*********************************************************/
-#include <stddef.h> /* size_t */
+#include "../common/zstd_deps.h" /* size_t */
#include "../zstd.h" /* DCtx, and some public functions */
#include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */
#include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */
@@ -48,12 +48,15 @@ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
* this function must be called with valid parameters only
* (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)
* in which case it cannot fail.
+ * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is
+ * defined in zstd_decompress_internal.h.
* Internal use only.
*/
void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
const U32* baseValue, const U32* nbAdditionalBits,
- unsigned tableLog);
+ unsigned tableLog, void* wksp, size_t wkspSize,
+ int bmi2);
#endif /* ZSTD_DEC_BLOCK_H */
diff --git a/Utilities/cmzstd/lib/decompress/zstd_decompress_internal.h b/Utilities/cmzstd/lib/decompress/zstd_decompress_internal.h
index 9ad96c554..ebda0c903 100644
--- a/Utilities/cmzstd/lib/decompress/zstd_decompress_internal.h
+++ b/Utilities/cmzstd/lib/decompress/zstd_decompress_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -27,26 +27,26 @@
/*-*******************************************************
* Constants
*********************************************************/
-static const U32 LL_base[MaxLL+1] = {
+static UNUSED_ATTR const U32 LL_base[MaxLL+1] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 18, 20, 22, 24, 28, 32, 40,
48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
0x2000, 0x4000, 0x8000, 0x10000 };
-static const U32 OF_base[MaxOff+1] = {
+static UNUSED_ATTR const U32 OF_base[MaxOff+1] = {
0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
-static const U32 OF_bits[MaxOff+1] = {
+static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31 };
-static const U32 ML_base[MaxML+1] = {
+static UNUSED_ATTR const U32 ML_base[MaxML+1] = {
3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26,
@@ -73,12 +73,16 @@ static const U32 ML_base[MaxML+1] = {
#define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log)))
+#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64))
+#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32))
+
typedef struct {
ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */
ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */
ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */
HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
U32 rep[ZSTD_REP_NUM];
+ U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32];
} ZSTD_entropyDTables_t;
typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
@@ -95,10 +99,12 @@ typedef enum {
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
} ZSTD_dictUses_e;
-typedef enum {
- ZSTD_obm_buffered = 0, /* Buffer the output */
- ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */
-} ZSTD_outBufferMode_e;
+/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */
+typedef struct {
+ const ZSTD_DDict** ddictPtrTable;
+ size_t ddictPtrTableSize;
+ size_t ddictPtrCount;
+} ZSTD_DDictHashSet;
struct ZSTD_DCtx_s
{
@@ -114,6 +120,7 @@ struct ZSTD_DCtx_s
const void* dictEnd; /* end of previous segment */
size_t expected;
ZSTD_frameHeader fParams;
+ U64 processedCSize;
U64 decodedSize;
blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
ZSTD_dStage stage;
@@ -122,6 +129,8 @@ struct ZSTD_DCtx_s
XXH64_state_t xxhState;
size_t headerSize;
ZSTD_format_e format;
+ ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */
+ U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */
const BYTE* litPtr;
ZSTD_customMem customMem;
size_t litSize;
@@ -135,6 +144,8 @@ struct ZSTD_DCtx_s
U32 dictID;
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
ZSTD_dictUses_e dictUses;
+ ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */
+ ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */
/* streaming */
ZSTD_dStreamStage streamStage;
@@ -152,7 +163,7 @@ struct ZSTD_DCtx_s
U32 legacyVersion;
U32 hostageByte;
int noForwardProgress;
- ZSTD_outBufferMode_e outBufferMode;
+ ZSTD_bufferMode_e outBufferMode;
ZSTD_outBuffer expectedOutBuffer;
/* workspace */
@@ -165,6 +176,11 @@ struct ZSTD_DCtx_s
void const* dictContentBeginForFuzzing;
void const* dictContentEndForFuzzing;
#endif
+
+ /* Tracing */
+#if ZSTD_TRACE
+ ZSTD_TraceCtx traceCtx;
+#endif
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
@@ -183,7 +199,7 @@ size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
* If yes, do nothing (continue on current segment).
* If not, classify previous segment as "external dictionary", and start a new segment.
* This function cannot fail. */
-void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst);
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);
#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
diff --git a/Utilities/cmzstd/lib/deprecated/zbuff.h b/Utilities/cmzstd/lib/deprecated/zbuff.h
index 03cb14a03..b83ea0fed 100644
--- a/Utilities/cmzstd/lib/deprecated/zbuff.h
+++ b/Utilities/cmzstd/lib/deprecated/zbuff.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/deprecated/zbuff_common.c b/Utilities/cmzstd/lib/deprecated/zbuff_common.c
index 579bc4df1..e7d01a081 100644
--- a/Utilities/cmzstd/lib/deprecated/zbuff_common.c
+++ b/Utilities/cmzstd/lib/deprecated/zbuff_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/deprecated/zbuff_compress.c b/Utilities/cmzstd/lib/deprecated/zbuff_compress.c
index 2d20b1377..2e7226735 100644
--- a/Utilities/cmzstd/lib/deprecated/zbuff_compress.c
+++ b/Utilities/cmzstd/lib/deprecated/zbuff_compress.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/deprecated/zbuff_decompress.c b/Utilities/cmzstd/lib/deprecated/zbuff_decompress.c
index d3c49e84b..d73c0f35f 100644
--- a/Utilities/cmzstd/lib/deprecated/zbuff_decompress.c
+++ b/Utilities/cmzstd/lib/deprecated/zbuff_decompress.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
diff --git a/Utilities/cmzstd/lib/dictBuilder/cover.c b/Utilities/cmzstd/lib/dictBuilder/cover.c
index da54ef15f..8364444d1 100644
--- a/Utilities/cmzstd/lib/dictBuilder/cover.c
+++ b/Utilities/cmzstd/lib/dictBuilder/cover.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -26,47 +26,57 @@
#include <string.h> /* memset */
#include <time.h> /* clock */
+#ifndef ZDICT_STATIC_LINKING_ONLY
+# define ZDICT_STATIC_LINKING_ONLY
+#endif
+
#include "../common/mem.h" /* read */
#include "../common/pool.h"
#include "../common/threading.h"
-#include "cover.h"
#include "../common/zstd_internal.h" /* includes zstd.h */
-#ifndef ZDICT_STATIC_LINKING_ONLY
-#define ZDICT_STATIC_LINKING_ONLY
-#endif
-#include "zdict.h"
+#include "../zdict.h"
+#include "cover.h"
/*-*************************************
* Constants
***************************************/
#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))
-#define DEFAULT_SPLITPOINT 1.0
+#define COVER_DEFAULT_SPLITPOINT 1.0
/*-*************************************
* Console display
***************************************/
+#ifndef LOCALDISPLAYLEVEL
static int g_displayLevel = 2;
+#endif
+#undef DISPLAY
#define DISPLAY(...) \
{ \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
+#undef LOCALDISPLAYLEVEL
#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \
if (displayLevel >= l) { \
DISPLAY(__VA_ARGS__); \
} /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
+#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__)
+#ifndef LOCALDISPLAYUPDATE
+static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100;
+static clock_t g_time = 0;
+#endif
+#undef LOCALDISPLAYUPDATE
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
if (displayLevel >= l) { \
- if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \
+ if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
g_time = clock(); \
DISPLAY(__VA_ARGS__); \
} \
}
+#undef DISPLAYUPDATE
#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
-static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
-static clock_t g_time = 0;
/*-*************************************
* Hash table
@@ -120,9 +130,9 @@ static int COVER_map_init(COVER_map_t *map, U32 size) {
/**
* Internal hash function
*/
-static const U32 prime4bytes = 2654435761U;
+static const U32 COVER_prime4bytes = 2654435761U;
static U32 COVER_map_hash(COVER_map_t *map, U32 key) {
- return (key * prime4bytes) >> (32 - map->sizeLog);
+ return (key * COVER_prime4bytes) >> (32 - map->sizeLog);
}
/**
@@ -215,7 +225,7 @@ typedef struct {
} COVER_ctx_t;
/* We need a global context for qsort... */
-static COVER_ctx_t *g_ctx = NULL;
+static COVER_ctx_t *g_coverCtx = NULL;
/*-*************************************
* Helper functions
@@ -258,11 +268,11 @@ static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
/**
* Same as COVER_cmp() except ties are broken by pointer value
- * NOTE: g_ctx must be set to call this function. A global is required because
+ * NOTE: g_coverCtx must be set to call this function. A global is required because
* qsort doesn't take an opaque pointer.
*/
-static int COVER_strict_cmp(const void *lp, const void *rp) {
- int result = COVER_cmp(g_ctx, lp, rp);
+static int WIN_CDECL COVER_strict_cmp(const void *lp, const void *rp) {
+ int result = COVER_cmp(g_coverCtx, lp, rp);
if (result == 0) {
result = lp < rp ? -1 : 1;
}
@@ -271,8 +281,8 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
/**
* Faster version for d <= 8.
*/
-static int COVER_strict_cmp8(const void *lp, const void *rp) {
- int result = COVER_cmp8(g_ctx, lp, rp);
+static int WIN_CDECL COVER_strict_cmp8(const void *lp, const void *rp) {
+ int result = COVER_cmp8(g_coverCtx, lp, rp);
if (result == 0) {
result = lp < rp ? -1 : 1;
}
@@ -603,7 +613,7 @@ static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
/* qsort doesn't take an opaque pointer, so pass as a global.
* On OpenBSD qsort() is not guaranteed to be stable, their mergesort() is.
*/
- g_ctx = ctx;
+ g_coverCtx = ctx;
#if defined(__OpenBSD__)
mergesort(ctx->suffix, ctx->suffixSize, sizeof(U32),
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
@@ -946,7 +956,7 @@ void COVER_dictSelectionFree(COVER_dictSelection_t selection){
free(selection.dictContent);
}
-COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
+COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity,
size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,
size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize) {
@@ -954,8 +964,8 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
size_t largestCompressed = 0;
BYTE* customDictContentEnd = customDictContent + dictContentSize;
- BYTE * largestDictbuffer = (BYTE *)malloc(dictContentSize);
- BYTE * candidateDictBuffer = (BYTE *)malloc(dictContentSize);
+ BYTE * largestDictbuffer = (BYTE *)malloc(dictBufferCapacity);
+ BYTE * candidateDictBuffer = (BYTE *)malloc(dictBufferCapacity);
double regressionTolerance = ((double)params.shrinkDictMaxRegression / 100.0) + 1.00;
if (!largestDictbuffer || !candidateDictBuffer) {
@@ -967,7 +977,7 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
/* Initial dictionary size and compressed size */
memcpy(largestDictbuffer, customDictContent, dictContentSize);
dictContentSize = ZDICT_finalizeDictionary(
- largestDictbuffer, dictContentSize, customDictContent, dictContentSize,
+ largestDictbuffer, dictBufferCapacity, customDictContent, dictContentSize,
samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);
if (ZDICT_isError(dictContentSize)) {
@@ -1001,7 +1011,7 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
while (dictContentSize < largestDict) {
memcpy(candidateDictBuffer, largestDictbuffer, largestDict);
dictContentSize = ZDICT_finalizeDictionary(
- candidateDictBuffer, dictContentSize, customDictContentEnd - dictContentSize, dictContentSize,
+ candidateDictBuffer, dictBufferCapacity, customDictContentEnd - dictContentSize, dictContentSize,
samplesBuffer, samplesSizes, nbFinalizeSamples, params.zParams);
if (ZDICT_isError(dictContentSize)) {
@@ -1053,18 +1063,19 @@ typedef struct COVER_tryParameters_data_s {
* This function is thread safe if zstd is compiled with multithreaded support.
* It takes its parameters as an *OWNING* opaque pointer to support threading.
*/
-static void COVER_tryParameters(void *opaque) {
+static void COVER_tryParameters(void *opaque)
+{
/* Save parameters as local variables */
- COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t *)opaque;
+ COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t*)opaque;
const COVER_ctx_t *const ctx = data->ctx;
const ZDICT_cover_params_t parameters = data->parameters;
size_t dictBufferCapacity = data->dictBufferCapacity;
size_t totalCompressedSize = ERROR(GENERIC);
/* Allocate space for hash table, dict, and freqs */
COVER_map_t activeDmers;
- BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity);
+ BYTE* const dict = (BYTE*)malloc(dictBufferCapacity);
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
- U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
+ U32* const freqs = (U32*)malloc(ctx->suffixSize * sizeof(U32));
if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) {
DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n");
goto _cleanup;
@@ -1079,7 +1090,7 @@ static void COVER_tryParameters(void *opaque) {
{
const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict,
dictBufferCapacity, parameters);
- selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail,
+ selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail,
ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbTrainSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,
totalCompressedSize);
@@ -1094,19 +1105,18 @@ _cleanup:
free(data);
COVER_map_destroy(&activeDmers);
COVER_dictSelectionFree(selection);
- if (freqs) {
- free(freqs);
- }
+ free(freqs);
}
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
- void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer,
- const size_t *samplesSizes, unsigned nbSamples,
- ZDICT_cover_params_t *parameters) {
+ void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer,
+ const size_t* samplesSizes, unsigned nbSamples,
+ ZDICT_cover_params_t* parameters)
+{
/* constants */
const unsigned nbThreads = parameters->nbThreads;
const double splitPoint =
- parameters->splitPoint <= 0.0 ? DEFAULT_SPLITPOINT : parameters->splitPoint;
+ parameters->splitPoint <= 0.0 ? COVER_DEFAULT_SPLITPOINT : parameters->splitPoint;
const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;
const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d;
const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;
diff --git a/Utilities/cmzstd/lib/dictBuilder/cover.h b/Utilities/cmzstd/lib/dictBuilder/cover.h
index f2aa0e35e..1aacdddd6 100644
--- a/Utilities/cmzstd/lib/dictBuilder/cover.h
+++ b/Utilities/cmzstd/lib/dictBuilder/cover.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020, Facebook, Inc.
+ * Copyright (c) Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -8,6 +8,10 @@
* You may select, at your option, one of the above-listed licenses.
*/
+#ifndef ZDICT_STATIC_LINKING_ONLY
+# define ZDICT_STATIC_LINKING_ONLY
+#endif
+
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* malloc, free, qsort */
#include <string.h> /* memset */
@@ -16,10 +20,7 @@
#include "../common/pool.h"
#include "../common/threading.h"
#include "../common/zstd_internal.h" /* includes zstd.h */
-#ifndef ZDICT_STATIC_LINKING_ONLY
-#define ZDICT_STATIC_LINKING_ONLY
-#endif
-#include "zdict.h"
+#include "../zdict.h"
/**
* COVER_best_t is used for two purposes:
@@ -152,6 +153,6 @@ void COVER_dictSelectionFree(COVER_dictSelection_t selection);
* smallest dictionary within a specified regression of the compressed size
* from the largest dictionary.
*/
- COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent,
+ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBufferCapacity,
size_t dictContentSize, const BYTE* samplesBuffer, const size_t* samplesSizes, unsigned nbFinalizeSamples,
size_t nbCheckSamples, size_t nbSamples, ZDICT_cover_params_t params, size_t* offsets, size_t totalCompressedSize);
diff --git a/Utilities/cmzstd/lib/dictBuilder/divsufsort.c b/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
index ead922044..a2870fb3b 100644
--- a/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
+++ b/Utilities/cmzstd/lib/dictBuilder/divsufsort.c
@@ -1576,7 +1576,7 @@ note:
/* Construct the inverse suffix array of type B* suffixes using trsort. */
trsort(ISAb, SA, m, 1);
- /* Set the sorted order of tyoe B* suffixes. */
+ /* Set the sorted order of type B* suffixes. */
for(i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) {
for(--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) { }
if(0 <= i) {
diff --git a/Utilities/cmzstd/lib/dictBuilder/fastcover.c b/Utilities/cmzstd/lib/dictBuilder/fastcover.c
index 485c333b5..ed789f92f 100644
--- a/Utilities/cmzstd/lib/dictBuilder/fastcover.c
+++ b/Utilities/cmzstd/lib/dictBuilder/fastcover.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2020, Facebook, Inc.
+ * Copyright (c) Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -16,15 +16,17 @@
#include <string.h> /* memset */
#include <time.h> /* clock */
+#ifndef ZDICT_STATIC_LINKING_ONLY
+# define ZDICT_STATIC_LINKING_ONLY
+#endif
+
#include "../common/mem.h" /* read */
#include "../common/pool.h"
#include "../common/threading.h"
-#include "cover.h"
#include "../common/zstd_internal.h" /* includes zstd.h */
-#ifndef ZDICT_STATIC_LINKING_ONLY
-#define ZDICT_STATIC_LINKING_ONLY
-#endif
-#include "zdict.h"
+#include "../compress/zstd_compress_internal.h" /* ZSTD_hash*() */
+#include "../zdict.h"
+#include "cover.h"
/*-*************************************
@@ -33,7 +35,7 @@
#define FASTCOVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((unsigned)-1) : ((unsigned)1 GB))
#define FASTCOVER_MAX_F 31
#define FASTCOVER_MAX_ACCEL 10
-#define DEFAULT_SPLITPOINT 0.75
+#define FASTCOVER_DEFAULT_SPLITPOINT 0.75
#define DEFAULT_F 20
#define DEFAULT_ACCEL 1
@@ -41,50 +43,50 @@
/*-*************************************
* Console display
***************************************/
+#ifndef LOCALDISPLAYLEVEL
static int g_displayLevel = 2;
+#endif
+#undef DISPLAY
#define DISPLAY(...) \
{ \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
}
+#undef LOCALDISPLAYLEVEL
#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \
if (displayLevel >= l) { \
DISPLAY(__VA_ARGS__); \
} /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
+#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__)
+#ifndef LOCALDISPLAYUPDATE
+static const clock_t g_refreshRate = CLOCKS_PER_SEC * 15 / 100;
+static clock_t g_time = 0;
+#endif
+#undef LOCALDISPLAYUPDATE
#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \
if (displayLevel >= l) { \
- if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) { \
+ if ((clock() - g_time > g_refreshRate) || (displayLevel >= 4)) { \
g_time = clock(); \
DISPLAY(__VA_ARGS__); \
} \
}
+#undef DISPLAYUPDATE
#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__)
-static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100;
-static clock_t g_time = 0;
/*-*************************************
* Hash Functions
***************************************/
-static const U64 prime6bytes = 227718039650203ULL;
-static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
-static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
-
-static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
-static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
-static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
-
-
/**
- * Hash the d-byte value pointed to by p and mod 2^f
+ * Hash the d-byte value pointed to by p and mod 2^f into the frequency vector
*/
-static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 h, unsigned d) {
+static size_t FASTCOVER_hashPtrToIndex(const void* p, U32 f, unsigned d) {
if (d == 6) {
- return ZSTD_hash6Ptr(p, h) & ((1 << h) - 1);
+ return ZSTD_hash6Ptr(p, f);
}
- return ZSTD_hash8Ptr(p, h) & ((1 << h) - 1);
+ return ZSTD_hash8Ptr(p, f);
}
@@ -461,20 +463,20 @@ typedef struct FASTCOVER_tryParameters_data_s {
* This function is thread safe if zstd is compiled with multithreaded support.
* It takes its parameters as an *OWNING* opaque pointer to support threading.
*/
-static void FASTCOVER_tryParameters(void *opaque)
+static void FASTCOVER_tryParameters(void* opaque)
{
/* Save parameters as local variables */
- FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t *)opaque;
+ FASTCOVER_tryParameters_data_t *const data = (FASTCOVER_tryParameters_data_t*)opaque;
const FASTCOVER_ctx_t *const ctx = data->ctx;
const ZDICT_cover_params_t parameters = data->parameters;
size_t dictBufferCapacity = data->dictBufferCapacity;
size_t totalCompressedSize = ERROR(GENERIC);
/* Initialize array to keep track of frequency of dmer within activeSegment */
- U16* segmentFreqs = (U16 *)calloc(((U64)1 << ctx->f), sizeof(U16));
+ U16* segmentFreqs = (U16*)calloc(((U64)1 << ctx->f), sizeof(U16));
/* Allocate space for hash table, dict, and freqs */
- BYTE *const dict = (BYTE * const)malloc(dictBufferCapacity);
+ BYTE *const dict = (BYTE*)malloc(dictBufferCapacity);
COVER_dictSelection_t selection = COVER_dictSelectionError(ERROR(GENERIC));
- U32 *freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32));
+ U32* freqs = (U32*) malloc(((U64)1 << ctx->f) * sizeof(U32));
if (!segmentFreqs || !dict || !freqs) {
DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n");
goto _cleanup;
@@ -486,7 +488,7 @@ static void FASTCOVER_tryParameters(void *opaque)
parameters, segmentFreqs);
const unsigned nbFinalizeSamples = (unsigned)(ctx->nbTrainSamples * ctx->accelParams.finalize / 100);
- selection = COVER_selectDict(dict + tail, dictBufferCapacity - tail,
+ selection = COVER_selectDict(dict + tail, dictBufferCapacity, dictBufferCapacity - tail,
ctx->samples, ctx->samplesSizes, nbFinalizeSamples, ctx->nbTrainSamples, ctx->nbSamples, parameters, ctx->offsets,
totalCompressedSize);
@@ -617,7 +619,7 @@ ZDICT_optimizeTrainFromBuffer_fastCover(
/* constants */
const unsigned nbThreads = parameters->nbThreads;
const double splitPoint =
- parameters->splitPoint <= 0.0 ? DEFAULT_SPLITPOINT : parameters->splitPoint;
+ parameters->splitPoint <= 0.0 ? FASTCOVER_DEFAULT_SPLITPOINT : parameters->splitPoint;
const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d;
const unsigned kMaxD = parameters->d == 0 ? 8 : parameters->d;
const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;
diff --git a/Utilities/cmzstd/lib/dictBuilder/zdict.c b/Utilities/cmzstd/lib/dictBuilder/zdict.c
index 6d0b04231..459cbe4d1 100644
--- a/Utilities/cmzstd/lib/dictBuilder/zdict.c
+++ b/Utilities/cmzstd/lib/dictBuilder/zdict.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -23,9 +23,13 @@
/* Unix Large Files support (>4GB) */
#define _FILE_OFFSET_BITS 64
#if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */
+# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE
+# endif
#elif ! defined(__LP64__) /* No point defining Large file for 64 bit */
+# ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
+# endif
#endif
@@ -37,18 +41,19 @@
#include <stdio.h> /* fprintf, fopen, ftello64 */
#include <time.h> /* clock */
+#ifndef ZDICT_STATIC_LINKING_ONLY
+# define ZDICT_STATIC_LINKING_ONLY
+#endif
+#define HUF_STATIC_LINKING_ONLY
+
#include "../common/mem.h" /* read */
#include "../common/fse.h" /* FSE_normalizeCount, FSE_writeNCount */
-#define HUF_STATIC_LINKING_ONLY
#include "../common/huf.h" /* HUF_buildCTable, HUF_writeCTable */
#include "../common/zstd_internal.h" /* includes zstd.h */
#include "../common/xxhash.h" /* XXH64 */
-#include "divsufsort.h"
-#ifndef ZDICT_STATIC_LINKING_ONLY
-# define ZDICT_STATIC_LINKING_ONLY
-#endif
-#include "zdict.h"
#include "../compress/zstd_compress_internal.h" /* ZSTD_loadCEntropy() */
+#include "../zdict.h"
+#include "divsufsort.h"
/*-*************************************
@@ -62,14 +67,15 @@
#define NOISELENGTH 32
-static const int g_compressionLevel_default = 3;
static const U32 g_selectivity_default = 9;
/*-*************************************
* Console display
***************************************/
+#undef DISPLAY
#define DISPLAY(...) { fprintf(stderr, __VA_ARGS__); fflush( stderr ); }
+#undef DISPLAYLEVEL
#define DISPLAYLEVEL(l, ...) if (notificationLevel>=l) { DISPLAY(__VA_ARGS__); } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */
static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; }
@@ -105,20 +111,17 @@ size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictSize)
size_t headerSize;
if (dictSize <= 8 || MEM_readLE32(dictBuffer) != ZSTD_MAGIC_DICTIONARY) return ERROR(dictionary_corrupted);
- { unsigned offcodeMaxValue = MaxOff;
- ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t));
+ { ZSTD_compressedBlockState_t* bs = (ZSTD_compressedBlockState_t*)malloc(sizeof(ZSTD_compressedBlockState_t));
U32* wksp = (U32*)malloc(HUF_WORKSPACE_SIZE);
- short* offcodeNCount = (short*)malloc((MaxOff+1)*sizeof(short));
- if (!bs || !wksp || !offcodeNCount) {
+ if (!bs || !wksp) {
headerSize = ERROR(memory_allocation);
} else {
ZSTD_reset_compressedBlockState(bs);
- headerSize = ZSTD_loadCEntropy(bs, wksp, offcodeNCount, &offcodeMaxValue, dictBuffer, dictSize);
+ headerSize = ZSTD_loadCEntropy(bs, wksp, dictBuffer, dictSize);
}
free(bs);
free(wksp);
- free(offcodeNCount);
}
return headerSize;
@@ -532,6 +535,7 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,
clock_t displayClock = 0;
clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10;
+# undef DISPLAYUPDATE
# define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \
if (ZDICT_clockSpan(displayClock) > refreshRate) \
{ displayClock = clock(); DISPLAY(__VA_ARGS__); \
@@ -706,7 +710,7 @@ static void ZDICT_flatLit(unsigned* countLit)
#define OFFCODE_MAX 30 /* only applicable to first block */
static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
- unsigned compressionLevel,
+ int compressionLevel,
const void* srcBuffer, const size_t* fileSizes, unsigned nbFiles,
const void* dictBuffer, size_t dictBufferSize,
unsigned notificationLevel)
@@ -741,7 +745,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
memset(repOffset, 0, sizeof(repOffset));
repOffset[1] = repOffset[4] = repOffset[8] = 1;
memset(bestRepOffset, 0, sizeof(bestRepOffset));
- if (compressionLevel==0) compressionLevel = g_compressionLevel_default;
+ if (compressionLevel==0) compressionLevel = ZSTD_CLEVEL_DEFAULT;
params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize);
esr.dict = ZSTD_createCDict_advanced(dictBuffer, dictBufferSize, ZSTD_dlm_byRef, ZSTD_dct_rawContent, params.cParams, ZSTD_defaultCMem);
@@ -786,7 +790,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
/* note : the result of this phase should be used to better appreciate the impact on statistics */
total=0; for (u=0; u<=offcodeMax; u++) total+=offcodeCount[u];
- errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax);
+ errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax, /* useLowProbCount */ 1);
if (FSE_isError(errorCode)) {
eSize = errorCode;
DISPLAYLEVEL(1, "FSE_normalizeCount error with offcodeCount \n");
@@ -795,7 +799,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
Offlog = (U32)errorCode;
total=0; for (u=0; u<=MaxML; u++) total+=matchLengthCount[u];
- errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML);
+ errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML, /* useLowProbCount */ 1);
if (FSE_isError(errorCode)) {
eSize = errorCode;
DISPLAYLEVEL(1, "FSE_normalizeCount error with matchLengthCount \n");
@@ -804,7 +808,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
mlLog = (U32)errorCode;
total=0; for (u=0; u<=MaxLL; u++) total+=litLengthCount[u];
- errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL);
+ errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL, /* useLowProbCount */ 1);
if (FSE_isError(errorCode)) {
eSize = errorCode;
DISPLAYLEVEL(1, "FSE_normalizeCount error with litLengthCount \n");
@@ -893,7 +897,7 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
size_t hSize;
#define HBUFFSIZE 256 /* should prove large enough for all entropy headers */
BYTE header[HBUFFSIZE];
- int const compressionLevel = (params.compressionLevel == 0) ? g_compressionLevel_default : params.compressionLevel;
+ int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel;
U32 const notificationLevel = params.notificationLevel;
/* check conditions */
@@ -939,7 +943,7 @@ static size_t ZDICT_addEntropyTablesFromBuffer_advanced(
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
ZDICT_params_t params)
{
- int const compressionLevel = (params.compressionLevel == 0) ? g_compressionLevel_default : params.compressionLevel;
+ int const compressionLevel = (params.compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : params.compressionLevel;
U32 const notificationLevel = params.notificationLevel;
size_t hSize = 8;
@@ -968,16 +972,11 @@ static size_t ZDICT_addEntropyTablesFromBuffer_advanced(
return MIN(dictBufferCapacity, hSize+dictContentSize);
}
-/* Hidden declaration for dbio.c */
-size_t ZDICT_trainFromBuffer_unsafe_legacy(
- void* dictBuffer, size_t maxDictSize,
- const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
- ZDICT_legacy_params_t params);
/*! ZDICT_trainFromBuffer_unsafe_legacy() :
-* Warning : `samplesBuffer` must be followed by noisy guard band.
+* Warning : `samplesBuffer` must be followed by noisy guard band !!!
* @return : size of dictionary, or an error code which can be tested with ZDICT_isError()
*/
-size_t ZDICT_trainFromBuffer_unsafe_legacy(
+static size_t ZDICT_trainFromBuffer_unsafe_legacy(
void* dictBuffer, size_t maxDictSize,
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
ZDICT_legacy_params_t params)
@@ -1114,8 +1113,8 @@ size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
memset(&params, 0, sizeof(params));
params.d = 8;
params.steps = 4;
- /* Default to level 6 since no compression level information is available */
- params.zParams.compressionLevel = 3;
+ /* Use default level since no compression level information is available */
+ params.zParams.compressionLevel = ZSTD_CLEVEL_DEFAULT;
#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=1)
params.zParams.notificationLevel = DEBUGLEVEL;
#endif
diff --git a/Utilities/cmzstd/lib/dictBuilder/zdict.h b/Utilities/cmzstd/lib/zdict.h
index ff2e77faf..75b05dbf4 100644
--- a/Utilities/cmzstd/lib/dictBuilder/zdict.h
+++ b/Utilities/cmzstd/lib/zdict.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -36,6 +36,145 @@ extern "C" {
# define ZDICTLIB_API ZDICTLIB_VISIBILITY
#endif
+/*******************************************************************************
+ * Zstd dictionary builder
+ *
+ * FAQ
+ * ===
+ * Why should I use a dictionary?
+ * ------------------------------
+ *
+ * Zstd can use dictionaries to improve compression ratio of small data.
+ * Traditionally small files don't compress well because there is very little
+ * repetion in a single sample, since it is small. But, if you are compressing
+ * many similar files, like a bunch of JSON records that share the same
+ * structure, you can train a dictionary on ahead of time on some samples of
+ * these files. Then, zstd can use the dictionary to find repetitions that are
+ * present across samples. This can vastly improve compression ratio.
+ *
+ * When is a dictionary useful?
+ * ----------------------------
+ *
+ * Dictionaries are useful when compressing many small files that are similar.
+ * The larger a file is, the less benefit a dictionary will have. Generally,
+ * we don't expect dictionary compression to be effective past 100KB. And the
+ * smaller a file is, the more we would expect the dictionary to help.
+ *
+ * How do I use a dictionary?
+ * --------------------------
+ *
+ * Simply pass the dictionary to the zstd compressor with
+ * `ZSTD_CCtx_loadDictionary()`. The same dictionary must then be passed to
+ * the decompressor, using `ZSTD_DCtx_loadDictionary()`. There are other
+ * more advanced functions that allow selecting some options, see zstd.h for
+ * complete documentation.
+ *
+ * What is a zstd dictionary?
+ * --------------------------
+ *
+ * A zstd dictionary has two pieces: Its header, and its content. The header
+ * contains a magic number, the dictionary ID, and entropy tables. These
+ * entropy tables allow zstd to save on header costs in the compressed file,
+ * which really matters for small data. The content is just bytes, which are
+ * repeated content that is common across many samples.
+ *
+ * What is a raw content dictionary?
+ * ---------------------------------
+ *
+ * A raw content dictionary is just bytes. It doesn't have a zstd dictionary
+ * header, a dictionary ID, or entropy tables. Any buffer is a valid raw
+ * content dictionary.
+ *
+ * How do I train a dictionary?
+ * ----------------------------
+ *
+ * Gather samples from your use case. These samples should be similar to each
+ * other. If you have several use cases, you could try to train one dictionary
+ * per use case.
+ *
+ * Pass those samples to `ZDICT_trainFromBuffer()` and that will train your
+ * dictionary. There are a few advanced versions of this function, but this
+ * is a great starting point. If you want to further tune your dictionary
+ * you could try `ZDICT_optimizeTrainFromBuffer_cover()`. If that is too slow
+ * you can try `ZDICT_optimizeTrainFromBuffer_fastCover()`.
+ *
+ * If the dictionary training function fails, that is likely because you
+ * either passed too few samples, or a dictionary would not be effective
+ * for your data. Look at the messages that the dictionary trainer printed,
+ * if it doesn't say too few samples, then a dictionary would not be effective.
+ *
+ * How large should my dictionary be?
+ * ----------------------------------
+ *
+ * A reasonable dictionary size, the `dictBufferCapacity`, is about 100KB.
+ * The zstd CLI defaults to a 110KB dictionary. You likely don't need a
+ * dictionary larger than that. But, most use cases can get away with a
+ * smaller dictionary. The advanced dictionary builders can automatically
+ * shrink the dictionary for you, and select a the smallest size that
+ * doesn't hurt compression ratio too much. See the `shrinkDict` parameter.
+ * A smaller dictionary can save memory, and potentially speed up
+ * compression.
+ *
+ * How many samples should I provide to the dictionary builder?
+ * ------------------------------------------------------------
+ *
+ * We generally recommend passing ~100x the size of the dictionary
+ * in samples. A few thousand should suffice. Having too few samples
+ * can hurt the dictionaries effectiveness. Having more samples will
+ * only improve the dictionaries effectiveness. But having too many
+ * samples can slow down the dictionary builder.
+ *
+ * How do I determine if a dictionary will be effective?
+ * -----------------------------------------------------
+ *
+ * Simply train a dictionary and try it out. You can use zstd's built in
+ * benchmarking tool to test the dictionary effectiveness.
+ *
+ * # Benchmark levels 1-3 without a dictionary
+ * zstd -b1e3 -r /path/to/my/files
+ * # Benchmark levels 1-3 with a dictioanry
+ * zstd -b1e3 -r /path/to/my/files -D /path/to/my/dictionary
+ *
+ * When should I retrain a dictionary?
+ * -----------------------------------
+ *
+ * You should retrain a dictionary when its effectiveness drops. Dictionary
+ * effectiveness drops as the data you are compressing changes. Generally, we do
+ * expect dictionaries to "decay" over time, as your data changes, but the rate
+ * at which they decay depends on your use case. Internally, we regularly
+ * retrain dictionaries, and if the new dictionary performs significantly
+ * better than the old dictionary, we will ship the new dictionary.
+ *
+ * I have a raw content dictionary, how do I turn it into a zstd dictionary?
+ * -------------------------------------------------------------------------
+ *
+ * If you have a raw content dictionary, e.g. by manually constructing it, or
+ * using a third-party dictionary builder, you can turn it into a zstd
+ * dictionary by using `ZDICT_finalizeDictionary()`. You'll also have to
+ * provide some samples of the data. It will add the zstd header to the
+ * raw content, which contains a dictionary ID and entropy tables, which
+ * will improve compression ratio, and allow zstd to write the dictionary ID
+ * into the frame, if you so choose.
+ *
+ * Do I have to use zstd's dictionary builder?
+ * -------------------------------------------
+ *
+ * No! You can construct dictionary content however you please, it is just
+ * bytes. It will always be valid as a raw content dictionary. If you want
+ * a zstd dictionary, which can improve compression ratio, use
+ * `ZDICT_finalizeDictionary()`.
+ *
+ * What is the attack surface of a zstd dictionary?
+ * ------------------------------------------------
+ *
+ * Zstd is heavily fuzz tested, including loading fuzzed dictionaries, so
+ * zstd should never crash, or access out-of-bounds memory no matter what
+ * the dictionary is. However, if an attacker can control the dictionary
+ * during decompression, they can cause zstd to generate arbitrary bytes,
+ * just like if they controlled the compressed data.
+ *
+ ******************************************************************************/
+
/*! ZDICT_trainFromBuffer():
* Train a dictionary from an array of samples.
@@ -64,7 +203,14 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap
typedef struct {
int compressionLevel; /*< optimize for a specific zstd compression level; 0 means default */
unsigned notificationLevel; /*< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */
- unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value) */
+ unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value)
+ * NOTE: The zstd format reserves some dictionary IDs for future use.
+ * You may use them in private settings, but be warned that they
+ * may be used by zstd in a public dictionary registry in the future.
+ * These dictionary IDs are:
+ * - low range : <= 32767
+ * - high range : >= (2^31)
+ */
} ZDICT_params_t;
/*! ZDICT_finalizeDictionary():
@@ -264,10 +410,11 @@ typedef struct {
* Note: ZDICT_trainFromBuffer_legacy() will send notifications into stderr if instructed to, using notificationLevel>0.
*/
ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy(
- void *dictBuffer, size_t dictBufferCapacity,
- const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples,
+ void* dictBuffer, size_t dictBufferCapacity,
+ const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
ZDICT_legacy_params_t parameters);
+
/* Deprecation warnings */
/* It is generally possible to disable deprecation warnings from compiler,
for example with -Wno-deprecated-declarations for gcc
@@ -279,7 +426,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy(
# define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define ZDICT_DEPRECATED(message) [[deprecated(message)]] ZDICTLIB_API
-# elif (ZDICT_GCC_VERSION >= 405) || defined(__clang__)
+# elif defined(__clang__) || (ZDICT_GCC_VERSION >= 405)
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated(message)))
# elif (ZDICT_GCC_VERSION >= 301)
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated))
diff --git a/Utilities/cmzstd/lib/zstd.h b/Utilities/cmzstd/lib/zstd.h
index 8c6fc6ae9..4651e6c4d 100644
--- a/Utilities/cmzstd/lib/zstd.h
+++ b/Utilities/cmzstd/lib/zstd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -71,17 +71,22 @@ extern "C" {
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
-#define ZSTD_VERSION_MINOR 4
-#define ZSTD_VERSION_RELEASE 5
-
+#define ZSTD_VERSION_MINOR 5
+#define ZSTD_VERSION_RELEASE 0
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
-ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */
+
+/*! ZSTD_versionNumber() :
+ * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */
+ZSTDLIB_API unsigned ZSTD_versionNumber(void);
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
#define ZSTD_QUOTE(str) #str
#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
-ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */
+
+/*! ZSTD_versionString() :
+ * Return runtime library version, like "1.4.5". Requires v1.3.0+. */
+ZSTDLIB_API const char* ZSTD_versionString(void);
/* *************************************
* Default constant
@@ -104,7 +109,6 @@ ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
-
/***************************************
* Simple API
***************************************/
@@ -161,7 +165,7 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
* @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
-/*! ZSTD_findFrameCompressedSize() :
+/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+
* `src` should point to the start of a ZSTD frame or skippable frame.
* `srcSize` must be >= first frame size
* @return : the compressed size of the first frame starting at `src`,
@@ -175,8 +179,9 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
-ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
+ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
+ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
/***************************************
@@ -194,7 +199,7 @@ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compres
*/
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
-ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
+ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */
/*! ZSTD_compressCCtx() :
* Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
@@ -217,7 +222,7 @@ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
* Use one context per thread for parallel execution. */
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
-ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
+ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */
/*! ZSTD_decompressDCtx() :
* Same as ZSTD_decompress(),
@@ -229,9 +234,9 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
const void* src, size_t srcSize);
-/***************************************
-* Advanced compression API
-***************************************/
+/*********************************************
+* Advanced compression API (Requires v1.4.0+)
+**********************************************/
/* API design :
* Parameters are pushed one by one into an existing context,
@@ -261,7 +266,6 @@ typedef enum { ZSTD_fast=1,
Only the order (from fast to strong) is guaranteed */
} ZSTD_strategy;
-
typedef enum {
/* compression parameters
@@ -327,14 +331,15 @@ typedef enum {
* The higher the value of selected strategy, the more complex it is,
* resulting in stronger and slower compression.
* Special: value 0 means "use default strategy". */
-
/* LDM mode parameters */
ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
* This parameter is designed to improve compression ratio
* for large inputs, by finding large matches at long distance.
* It increases memory usage and window size.
* Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB
- * except when expressly set to a different value. */
+ * except when expressly set to a different value.
+ * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and
+ * compression strategy >= ZSTD_btopt (== compression level 16+) */
ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2.
* Larger values increase memory usage and compression ratio,
* but decrease compression speed.
@@ -365,20 +370,24 @@ typedef enum {
ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */
/* multi-threading parameters */
- /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
- * They return an error otherwise. */
+ /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
+ * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.
+ * In a situation where it's unknown if the linked library supports multi-threading or not,
+ * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.
+ */
ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
- * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() :
+ * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :
* ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
- * while compression work is performed in parallel, within worker threads.
+ * while compression is performed in parallel, within worker thread(s).
* (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
* in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
* More workers improve speed, but also increase memory usage.
- * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned,
+ * compression is performed inside Caller's thread, and all invocations are blocking */
ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
* Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
* 0 means default, which is dynamically determined based on compression parameters.
- * Job size must be a minimum of overlap size, or 1 MB, whichever is largest.
+ * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.
* The minimum size is automatically and transparently enforced. */
ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size.
* The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
@@ -403,6 +412,13 @@ typedef enum {
* ZSTD_c_literalCompressionMode
* ZSTD_c_targetCBlockSize
* ZSTD_c_srcSizeHint
+ * ZSTD_c_enableDedicatedDictSearch
+ * ZSTD_c_stableInBuffer
+ * ZSTD_c_stableOutBuffer
+ * ZSTD_c_blockDelimiters
+ * ZSTD_c_validateSequences
+ * ZSTD_c_splitBlocks
+ * ZSTD_c_useRowMatchFinder
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly;
* also, the enums values themselves are unstable and can still change.
@@ -413,7 +429,15 @@ typedef enum {
ZSTD_c_experimentalParam4=1001,
ZSTD_c_experimentalParam5=1002,
ZSTD_c_experimentalParam6=1003,
- ZSTD_c_experimentalParam7=1004
+ ZSTD_c_experimentalParam7=1004,
+ ZSTD_c_experimentalParam8=1005,
+ ZSTD_c_experimentalParam9=1006,
+ ZSTD_c_experimentalParam10=1007,
+ ZSTD_c_experimentalParam11=1008,
+ ZSTD_c_experimentalParam12=1009,
+ ZSTD_c_experimentalParam13=1010,
+ ZSTD_c_experimentalParam14=1011,
+ ZSTD_c_experimentalParam15=1012
} ZSTD_cParameter;
typedef struct {
@@ -498,9 +522,9 @@ ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
const void* src, size_t srcSize);
-/***************************************
-* Advanced decompression API
-***************************************/
+/***********************************************
+* Advanced decompression API (Requires v1.4.0+)
+************************************************/
/* The advanced API pushes parameters one by one into an existing DCtx context.
* Parameters are sticky, and remain valid for all following frames
@@ -524,11 +548,15 @@ typedef enum {
* At the time of this writing, they include :
* ZSTD_d_format
* ZSTD_d_stableOutBuffer
+ * ZSTD_d_forceIgnoreChecksum
+ * ZSTD_d_refMultipleDDicts
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000,
- ZSTD_d_experimentalParam2=1001
+ ZSTD_d_experimentalParam2=1001,
+ ZSTD_d_experimentalParam3=1002,
+ ZSTD_d_experimentalParam4=1003
} ZSTD_dParameter;
@@ -642,7 +670,7 @@ typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
/*===== ZSTD_CStream management functions =====*/
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
-ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
+ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */
/*===== Streaming compression functions =====*/
typedef enum {
@@ -658,14 +686,15 @@ typedef enum {
: note : multithreaded compression will block to flush as much output as possible. */
} ZSTD_EndDirective;
-/*! ZSTD_compressStream2() :
+/*! ZSTD_compressStream2() : Requires v1.4.0+
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
* - output->pos must be <= dstCapacity, input->pos must be <= srcSize
* - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
+ * - endOp must be a valid directive
* - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available,
+ * - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,
* and then immediately returns, just indicating that there is some data remaining to be flushed.
* The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
* - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
@@ -703,11 +732,11 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
/* *****************************************************************************
- * This following is a legacy streaming API.
+ * This following is a legacy streaming API, available since v1.0+ .
* It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
* It is redundant, but remains fully supported.
- * Advanced parameters and dictionary compression can only be used through the
- * new API.
+ * Streaming in combination with advanced parameters and dictionary compression
+ * can only be used through the new API.
******************************************************************************/
/*!
@@ -762,7 +791,7 @@ typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
/*===== ZSTD_DStream management functions =====*/
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
-ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
+ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */
/*===== Streaming decompression functions =====*/
@@ -785,7 +814,7 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
/*! ZSTD_compress_usingDict() :
* Compression at an explicit compression level using a Dictionary.
* A dictionary can be any arbitrary data segment (also called a prefix),
- * or a buffer with specified information (see dictBuilder/zdict.h).
+ * or a buffer with specified information (see zdict.h).
* Note : This function loads the dictionary, resulting in significant startup delay.
* It's intended for a dictionary used only once.
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
@@ -828,7 +857,8 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize
int compressionLevel);
/*! ZSTD_freeCDict() :
- * Function frees memory allocated by ZSTD_createCDict(). */
+ * Function frees memory allocated by ZSTD_createCDict().
+ * If a NULL pointer is passed, no operation is performed. */
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
/*! ZSTD_compress_usingCDict() :
@@ -850,7 +880,8 @@ typedef struct ZSTD_DDict_s ZSTD_DDict;
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
/*! ZSTD_freeDDict() :
- * Function frees memory allocated with ZSTD_createDDict() */
+ * Function frees memory allocated with ZSTD_createDDict()
+ * If a NULL pointer is passed, no operation is performed. */
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
/*! ZSTD_decompress_usingDDict() :
@@ -866,19 +897,25 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
* Dictionary helper functions
*******************************/
-/*! ZSTD_getDictID_fromDict() :
+/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
* It can still be loaded, but as a content-only dictionary. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
-/*! ZSTD_getDictID_fromDDict() :
+/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+
+ * Provides the dictID of the dictionary loaded into `cdict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);
+
+/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+
* Provides the dictID of the dictionary loaded into `ddict`.
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
-/*! ZSTD_getDictID_fromFrame() :
+/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+
* Provides the dictID required to decompressed the frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
@@ -892,7 +929,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
/*******************************************************************************
- * Advanced dictionary and prefix API
+ * Advanced dictionary and prefix API (Requires v1.4.0+)
*
* This API allows dictionaries to be used with ZSTD_compress2(),
* ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
@@ -901,7 +938,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
******************************************************************************/
-/*! ZSTD_CCtx_loadDictionary() :
+/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+
* Create an internal CDict from `dict` buffer.
* Decompression will have to use same dictionary.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
@@ -920,11 +957,11 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
* to precisely select how dictionary content must be interpreted. */
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-/*! ZSTD_CCtx_refCDict() :
+/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+
* Reference a prepared dictionary, to be used for all next compressed frames.
* Note that compression parameters are enforced from within CDict,
* and supersede any compression parameter previously set within CCtx.
- * The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
+ * The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
* The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
* The dictionary will remain valid for future compressed frames using same CCtx.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
@@ -934,7 +971,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
* Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
-/*! ZSTD_CCtx_refPrefix() :
+/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+
* Reference a prefix (single-usage dictionary) for next compressed frame.
* A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
* Decompression will need same prefix to properly regenerate data.
@@ -955,7 +992,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
const void* prefix, size_t prefixSize);
-/*! ZSTD_DCtx_loadDictionary() :
+/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+
* Create an internal DDict from dict buffer,
* to be used to decompress next frames.
* The dictionary remains valid for all future frames, until explicitly invalidated.
@@ -972,9 +1009,16 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
*/
ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-/*! ZSTD_DCtx_refDDict() :
+/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+
* Reference a prepared dictionary, to be used to decompress next frames.
* The dictionary remains active for decompression of future frames using same DCtx.
+ *
+ * If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function
+ * will store the DDict references in a table, and the DDict used for decompression
+ * will be determined at decompression time, as per the dict ID in the frame.
+ * The memory for the table is allocated on the first call to refDDict, and can be
+ * freed with ZSTD_freeDCtx().
+ *
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
* Note 1 : Currently, only one dictionary can be managed.
* Referencing a new dictionary effectively "discards" any previous one.
@@ -983,7 +1027,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, s
*/
ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-/*! ZSTD_DCtx_refPrefix() :
+/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+
* Reference a prefix (single-usage dictionary) to decompress next frame.
* This is the reverse operation of ZSTD_CCtx_refPrefix(),
* and must use the same prefix as the one used during compression.
@@ -1004,7 +1048,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
/* === Memory management === */
-/*! ZSTD_sizeof_*() :
+/*! ZSTD_sizeof_*() : Requires v1.4.0+
* These functions give the _current_ memory usage of selected object.
* Note that object memory usage can evolve (increase or decrease) over time. */
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
@@ -1029,6 +1073,28 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
+/* Deprecation warnings :
+ * Should these warnings be a problem, it is generally possible to disable them,
+ * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.
+ * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.
+ */
+#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS
+# define ZSTD_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */
+#else
+# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
+# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API
+# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)
+# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message)))
+# elif defined(__GNUC__) && (__GNUC__ >= 3)
+# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated))
+# elif defined(_MSC_VER)
+# define ZSTD_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message))
+# else
+# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler")
+# define ZSTD_DEPRECATED(message) ZSTDLIB_API
+# endif
+#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */
+
/****************************************************************************************
* experimental API (static linking only)
****************************************************************************************
@@ -1100,21 +1166,40 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
typedef struct {
- unsigned int matchPos; /* Match pos in dst */
- /* If seqDef.offset > 3, then this is seqDef.offset - 3
- * If seqDef.offset < 3, then this is the corresponding repeat offset
- * But if seqDef.offset < 3 and litLength == 0, this is the
- * repeat offset before the corresponding repeat offset
- * And if seqDef.offset == 3 and litLength == 0, this is the
- * most recent repeat offset - 1
- */
- unsigned int offset;
- unsigned int litLength; /* Literal length */
- unsigned int matchLength; /* Match length */
- /* 0 when seq not rep and seqDef.offset otherwise
- * when litLength == 0 this will be <= 4, otherwise <= 3 like normal
- */
- unsigned int rep;
+ unsigned int offset; /* The offset of the match. (NOT the same as the offset code)
+ * If offset == 0 and matchLength == 0, this sequence represents the last
+ * literals in the block of litLength size.
+ */
+
+ unsigned int litLength; /* Literal length of the sequence. */
+ unsigned int matchLength; /* Match length of the sequence. */
+
+ /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.
+ * In this case, we will treat the sequence as a marker for a block boundary.
+ */
+
+ unsigned int rep; /* Represents which repeat offset is represented by the field 'offset'.
+ * Ranges from [0, 3].
+ *
+ * Repeat offsets are essentially previous offsets from previous sequences sorted in
+ * recency order. For more detail, see doc/zstd_compression_format.md
+ *
+ * If rep == 0, then 'offset' does not contain a repeat offset.
+ * If rep > 0:
+ * If litLength != 0:
+ * rep == 1 --> offset == repeat_offset_1
+ * rep == 2 --> offset == repeat_offset_2
+ * rep == 3 --> offset == repeat_offset_3
+ * If litLength == 0:
+ * rep == 1 --> offset == repeat_offset_2
+ * rep == 2 --> offset == repeat_offset_3
+ * rep == 3 --> offset == repeat_offset_1 - 1
+ *
+ * Note: This field is optional. ZSTD_generateSequences() will calculate the value of
+ * 'rep', but repeat offsets do not necessarily need to be calculated from an external
+ * sequence provider's perspective. For example, ZSTD_compressSequences() does not
+ * use this 'rep' field at all (as of now).
+ */
} ZSTD_Sequence;
typedef struct {
@@ -1157,6 +1242,18 @@ typedef enum {
} ZSTD_format_e;
typedef enum {
+ /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
+ ZSTD_d_validateChecksum = 0,
+ ZSTD_d_ignoreChecksum = 1
+} ZSTD_forceIgnoreChecksum_e;
+
+typedef enum {
+ /* Note: this enum controls ZSTD_d_refMultipleDDicts */
+ ZSTD_rmd_refSingleDDict = 0,
+ ZSTD_rmd_refMultipleDDicts = 1
+} ZSTD_refMultipleDDicts_e;
+
+typedef enum {
/* Note: this enum and the behavior it controls are effectively internal
* implementation details of the compressor. They are expected to continue
* to evolve and should be considered only in the context of extremely
@@ -1204,6 +1301,11 @@ typedef enum {
ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */
} ZSTD_literalCompressionMode_e;
+typedef enum {
+ ZSTD_urm_auto = 0, /* Automatically determine whether or not we use row matchfinder */
+ ZSTD_urm_disableRowMatchFinder = 1, /* Never use row matchfinder */
+ ZSTD_urm_enableRowMatchFinder = 2 /* Always use row matchfinder when applicable */
+} ZSTD_useRowMatchFinderMode_e;
/***************************************
* Frame size functions
@@ -1237,7 +1339,7 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t
* `srcSize` must be the _exact_ size of this series
* (i.e. there should be a frame boundary at `src + srcSize`)
* @return : - upper-bound for the decompressed size of all data in all successive frames
- * - if an error occured: ZSTD_CONTENTSIZE_ERROR
+ * - if an error occurred: ZSTD_CONTENTSIZE_ERROR
*
* note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
* note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
@@ -1253,14 +1355,91 @@ ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcS
* or an error code (if srcSize is too small) */
ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
-/*! ZSTD_getSequences() :
- * Extract sequences from the sequence store
+typedef enum {
+ ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
+ ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */
+} ZSTD_sequenceFormat_e;
+
+/*! ZSTD_generateSequences() :
+ * Generate sequences using ZSTD_compress2, given a source buffer.
+ *
+ * Each block will end with a dummy sequence
+ * with offset == 0, matchLength == 0, and litLength == length of last literals.
+ * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)
+ * simply acts as a block delimiter.
+ *
* zc can be used to insert custom compression params.
* This function invokes ZSTD_compress2
- * @return : number of sequences extracted
+ *
+ * The output of this function can be fed into ZSTD_compressSequences() with CCtx
+ * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters
+ * @return : number of sequences generated
+ */
+
+ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
+ size_t outSeqsSize, const void* src, size_t srcSize);
+
+/*! ZSTD_mergeBlockDelimiters() :
+ * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals
+ * by merging them into into the literals of the next sequence.
+ *
+ * As such, the final generated result has no explicit representation of block boundaries,
+ * and the final last literals segment is not represented in the sequences.
+ *
+ * The output of this function can be fed into ZSTD_compressSequences() with CCtx
+ * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters
+ * @return : number of sequences left after merging
+ */
+ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
+
+/*! ZSTD_compressSequences() :
+ * Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
+ * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.)
+ * The entire source is compressed into a single frame.
+ *
+ * The compression behavior changes based on cctx params. In particular:
+ * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain
+ * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on
+ * the block size derived from the cctx, and sequences may be split. This is the default setting.
+ *
+ * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain
+ * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.
+ *
+ * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined
+ * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for
+ * specifics regarding offset/matchlength requirements) then the function will bail out and return an error.
+ *
+ * In addition to the two adjustable experimental params, there are other important cctx params.
+ * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.
+ * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.
+ * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset
+ * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md
+ *
+ * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused.
+ * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly,
+ * and cannot emit an RLE block that disagrees with the repcode history
+ * @return : final compressed size or a ZSTD error.
*/
-ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
- size_t outSeqsSize, const void* src, size_t srcSize);
+ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
+ const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
+ const void* src, size_t srcSize);
+
+
+/*! ZSTD_writeSkippableFrame() :
+ * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * Skippable frames begin with a a 4-byte magic number. There are 16 possible choices of magic number,
+ * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.
+ * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so
+ * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, if the source size is not representable
+ * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, unsigned magicVariant);
/***************************************
@@ -1372,7 +1551,11 @@ ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
-static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
+static
+#ifdef __GNUC__
+__attribute__((__unused__))
+#endif
+ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
@@ -1385,12 +1568,38 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS
ZSTD_compressionParameters cParams,
ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
- ZSTD_dictLoadMethod_e dictLoadMethod,
- ZSTD_dictContentType_e dictContentType,
- ZSTD_customMem customMem);
+/* ! Thread pool :
+ * These prototypes make it possible to share a thread pool among multiple compression contexts.
+ * This can limit resources for applications with multiple threads where each one uses
+ * a threaded compression mode (via ZSTD_c_nbWorkers parameter).
+ * ZSTD_createThreadPool creates a new thread pool with a given number of threads.
+ * Note that the lifetime of such pool must exist while being used.
+ * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
+ * to use an internal thread pool).
+ * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
+ */
+typedef struct POOL_ctx_s ZSTD_threadPool;
+ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
+ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
+ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
+/*
+ * This API is temporary and is expected to change or disappear in the future!
+ */
+ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ const ZSTD_CCtx_params* cctxParams,
+ ZSTD_customMem customMem);
+
+ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem);
+
/***************************************
* Advanced compression functions
@@ -1430,18 +1639,20 @@ ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParame
/*! ZSTD_compress_advanced() :
* Note : this function is now DEPRECATED.
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
- * This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */
-ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
+ * This prototype will generate compilation warnings. */
+ZSTD_DEPRECATED("use ZSTD_compress2")
+size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
ZSTD_parameters params);
/*! ZSTD_compress_usingCDict_advanced() :
- * Note : this function is now REDUNDANT.
+ * Note : this function is now DEPRECATED.
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.
- * This prototype will be marked as deprecated and generate compilation warning in some future version */
-ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
+ * This prototype will generate compilation warnings. */
+ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary")
+size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict,
@@ -1503,7 +1714,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
/* Controls how the literals are compressed (default is auto).
* The value must be of type ZSTD_literalCompressionMode_e.
- * See ZSTD_literalCompressionMode_t enum definition for details.
+ * See ZSTD_literalCompressionMode_e enum definition for details.
*/
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
@@ -1518,12 +1729,189 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
* but compression ratio may regress significantly if guess considerably underestimates */
#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7
+/* Controls whether the new and experimental "dedicated dictionary search
+ * structure" can be used. This feature is still rough around the edges, be
+ * prepared for surprising behavior!
+ *
+ * How to use it:
+ *
+ * When using a CDict, whether to use this feature or not is controlled at
+ * CDict creation, and it must be set in a CCtxParams set passed into that
+ * construction (via ZSTD_createCDict_advanced2()). A compression will then
+ * use the feature or not based on how the CDict was constructed; the value of
+ * this param, set in the CCtx, will have no effect.
+ *
+ * However, when a dictionary buffer is passed into a CCtx, such as via
+ * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control
+ * whether the CDict that is created internally can use the feature or not.
+ *
+ * What it does:
+ *
+ * Normally, the internal data structures of the CDict are analogous to what
+ * would be stored in a CCtx after compressing the contents of a dictionary.
+ * To an approximation, a compression using a dictionary can then use those
+ * data structures to simply continue what is effectively a streaming
+ * compression where the simulated compression of the dictionary left off.
+ * Which is to say, the search structures in the CDict are normally the same
+ * format as in the CCtx.
+ *
+ * It is possible to do better, since the CDict is not like a CCtx: the search
+ * structures are written once during CDict creation, and then are only read
+ * after that, while the search structures in the CCtx are both read and
+ * written as the compression goes along. This means we can choose a search
+ * structure for the dictionary that is read-optimized.
+ *
+ * This feature enables the use of that different structure.
+ *
+ * Note that some of the members of the ZSTD_compressionParameters struct have
+ * different semantics and constraints in the dedicated search structure. It is
+ * highly recommended that you simply set a compression level in the CCtxParams
+ * you pass into the CDict creation call, and avoid messing with the cParams
+ * directly.
+ *
+ * Effects:
+ *
+ * This will only have any effect when the selected ZSTD_strategy
+ * implementation supports this feature. Currently, that's limited to
+ * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2.
+ *
+ * Note that this means that the CDict tables can no longer be copied into the
+ * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be
+ * useable. The dictionary can only be attached or reloaded.
+ *
+ * In general, you should expect compression to be faster--sometimes very much
+ * so--and CDict creation to be slightly slower. Eventually, we will probably
+ * make this mode the default.
+ */
+#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8
+
+/* ZSTD_c_stableInBuffer
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Tells the compressor that the ZSTD_inBuffer will ALWAYS be the same
+ * between calls, except for the modifications that zstd makes to pos (the
+ * caller must not modify pos). This is checked by the compressor, and
+ * compression will fail if it ever changes. This means the only flush
+ * mode that makes sense is ZSTD_e_end, so zstd will error if ZSTD_e_end
+ * is not used. The data in the ZSTD_inBuffer in the range [src, src + pos)
+ * MUST not be modified during compression or you will get data corruption.
+ *
+ * When this flag is enabled zstd won't allocate an input window buffer,
+ * because the user guarantees it can reference the ZSTD_inBuffer until
+ * the frame is complete. But, it will still allocate an output buffer
+ * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also
+ * avoid the memcpy() from the input buffer to the input window buffer.
+ *
+ * NOTE: ZSTD_compressStream2() will error if ZSTD_e_end is not used.
+ * That means this flag cannot be used with ZSTD_compressStream().
+ *
+ * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using
+ * this flag is ALWAYS memory safe, and will never access out-of-bounds
+ * memory. However, compression WILL fail if you violate the preconditions.
+ *
+ * WARNING: The data in the ZSTD_inBuffer in the range [dst, dst + pos) MUST
+ * not be modified during compression or you will get data corruption. This
+ * is because zstd needs to reference data in the ZSTD_inBuffer to find
+ * matches. Normally zstd maintains its own window buffer for this purpose,
+ * but passing this flag tells zstd to use the user provided buffer.
+ */
+#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9
+
+/* ZSTD_c_stableOutBuffer
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Tells he compressor that the ZSTD_outBuffer will not be resized between
+ * calls. Specifically: (out.size - out.pos) will never grow. This gives the
+ * compressor the freedom to say: If the compressed data doesn't fit in the
+ * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to
+ * always decompress directly into the output buffer, instead of decompressing
+ * into an internal buffer and copying to the output buffer.
+ *
+ * When this flag is enabled zstd won't allocate an output buffer, because
+ * it can write directly to the ZSTD_outBuffer. It will still allocate the
+ * input window buffer (see ZSTD_c_stableInBuffer).
+ *
+ * Zstd will check that (out.size - out.pos) never grows and return an error
+ * if it does. While not strictly necessary, this should prevent surprises.
+ */
+#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10
+
+/* ZSTD_c_blockDelimiters
+ * Default is 0 == ZSTD_sf_noBlockDelimiters.
+ *
+ * For use with sequence compression API: ZSTD_compressSequences().
+ *
+ * Designates whether or not the given array of ZSTD_Sequence contains block delimiters
+ * and last literals, which are defined as sequences with offset == 0 and matchLength == 0.
+ * See the definition of ZSTD_Sequence for more specifics.
+ */
+#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11
+
+/* ZSTD_c_validateSequences
+ * Default is 0 == disabled. Set to 1 to enable sequence validation.
+ *
+ * For use with sequence compression API: ZSTD_compressSequences().
+ * Designates whether or not we validate sequences provided to ZSTD_compressSequences()
+ * during function execution.
+ *
+ * Without validation, providing a sequence that does not conform to the zstd spec will cause
+ * undefined behavior, and may produce a corrupted block.
+ *
+ * With validation enabled, a if sequence is invalid (see doc/zstd_compression_format.md for
+ * specifics regarding offset/matchlength requirements) then the function will bail out and
+ * return an error.
+ *
+ */
+#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
+
+/* ZSTD_c_splitBlocks
+ * Default is 0 == disabled. Set to 1 to enable block splitting.
+ *
+ * Will attempt to split blocks in order to improve compression ratio at the cost of speed.
+ */
+#define ZSTD_c_splitBlocks ZSTD_c_experimentalParam13
+
+/* ZSTD_c_useRowMatchFinder
+ * Default is ZSTD_urm_auto.
+ * Controlled with ZSTD_useRowMatchFinderMode_e enum.
+ *
+ * By default, in ZSTD_urm_auto, when finalizing the compression parameters, the library
+ * will decide at runtime whether to use the row-based matchfinder based on support for SIMD
+ * instructions as well as the windowLog.
+ *
+ * Set to ZSTD_urm_disableRowMatchFinder to never use row-based matchfinder.
+ * Set to ZSTD_urm_enableRowMatchFinder to force usage of row-based matchfinder.
+ */
+#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14
+
+/* ZSTD_c_deterministicRefPrefix
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Zstd produces different results for prefix compression when the prefix is
+ * directly adjacent to the data about to be compressed vs. when it isn't.
+ * This is because zstd detects that the two buffers are contiguous and it can
+ * use a more efficient match finding algorithm. However, this produces different
+ * results than when the two buffers are non-contiguous. This flag forces zstd
+ * to always load the prefix in non-contiguous mode, even if it happens to be
+ * adjacent to the data, to guarantee determinism.
+ *
+ * If you really care about determinism when using a dictionary or prefix,
+ * like when doing delta compression, you should select this option. It comes
+ * at a speed penalty of about ~2.5% if the dictionary and data happened to be
+ * contiguous, and is free if they weren't contiguous. We don't expect that
+ * intentionally making the dictionary and data contiguous will be worth the
+ * cost to memcpy() the data.
+ */
+#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15
+
/*! ZSTD_CCtx_getParameter() :
* Get the requested compression parameter value, selected by enum ZSTD_cParameter,
* and store it into int* value.
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
+ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
/*! ZSTD_CCtx_params :
@@ -1538,13 +1926,13 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
* These parameters will be applied to
* all subsequent frames.
* - ZSTD_compressStream2() : Do compression using the CCtx.
- * - ZSTD_freeCCtxParams() : Free the memory.
+ * - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.
*
* This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
* for static allocation of CCtx for single-threaded compression.
*/
ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
-ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
+ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
/*! ZSTD_CCtxParams_reset() :
* Reset params to default values.
@@ -1563,11 +1951,13 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compre
*/
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
-/*! ZSTD_CCtxParams_setParameter() :
+/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+
* Similar to ZSTD_CCtx_setParameter.
* Set one compression parameter, selected by enum ZSTD_cParameter.
- * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams().
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Parameters must be applied to a ZSTD_CCtx using
+ * ZSTD_CCtx_setParametersUsingCCtxParams().
+ * @result : a code representing success or failure (which can be tested with
+ * ZSTD_isError()).
*/
ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
@@ -1576,7 +1966,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_c
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
+ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
* Apply a set of ZSTD_CCtx_params to the compression context.
@@ -1647,6 +2037,13 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre
*/
ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
+/*! ZSTD_DCtx_getParameter() :
+ * Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
+ * and store it into int* value.
+ * @return : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
+
/* ZSTD_d_format
* experimental parameter,
* allowing selection between ZSTD_format_e input compression formats
@@ -1684,12 +2081,49 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS
*/
#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
+/* ZSTD_d_forceIgnoreChecksum
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable
+ *
+ * Tells the decompressor to skip checksum validation during decompression, regardless
+ * of whether checksumming was specified during compression. This offers some
+ * slight performance benefits, and may be useful for debugging.
+ * Param has values of type ZSTD_forceIgnoreChecksum_e
+ */
+#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
+
+/* ZSTD_d_refMultipleDDicts
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable
+ *
+ * If enabled and dctx is allocated on the heap, then additional memory will be allocated
+ * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()
+ * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead
+ * store all references. At decompression time, the appropriate dictID is selected
+ * from the set of DDicts based on the dictID in the frame.
+ *
+ * Usage is simply calling ZSTD_refDDict() on multiple dict buffers.
+ *
+ * Param has values of byte ZSTD_refMultipleDDicts_e
+ *
+ * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory
+ * allocation for the hash table. ZSTD_freeDCtx() also frees this memory.
+ * Memory is allocated as per ZSTD_DCtx::customMem.
+ *
+ * Although this function allocates memory for the table, the user is still responsible for
+ * memory management of the underlying ZSTD_DDict* themselves.
+ */
+#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4
+
+
/*! ZSTD_DCtx_setFormat() :
+ * This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().
* Instruct the decoder context about what kind of data to decode next.
* This instruction is mandatory to decode data without a fully-formed header,
* such ZSTD_f_zstd1_magicless for example.
* @return : 0, or an error code (which can be tested using ZSTD_isError()). */
-ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
+ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead")
+size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
/*! ZSTD_decompressStream_simpleArgs() :
* Same as ZSTD_decompressStream(),
@@ -1711,8 +2145,9 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
********************************************************************/
/*===== Advanced Streaming compression functions =====*/
-/**! ZSTD_initCStream_srcSize() :
- * This function is deprecated, and equivalent to:
+
+/*! ZSTD_initCStream_srcSize() :
+ * This function is DEPRECATED, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
@@ -1721,15 +2156,15 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
* pledgedSrcSize must be correct. If it is not known at init time, use
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
* "0" also disables frame content size field. It may be enabled in the future.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t
-ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
int compressionLevel,
unsigned long long pledgedSrcSize);
-/**! ZSTD_initCStream_usingDict() :
- * This function is deprecated, and is equivalent to:
+/*! ZSTD_initCStream_usingDict() :
+ * This function is DEPRECATED, and is equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
@@ -1738,15 +2173,15 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
* dict == NULL or dictSize < 8, in which case no dict is used.
* Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t
-ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
int compressionLevel);
-/**! ZSTD_initCStream_advanced() :
- * This function is deprecated, and is approximately equivalent to:
+/*! ZSTD_initCStream_advanced() :
+ * This function is DEPRECATED, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* // Pseudocode: Set each zstd parameter and leave the rest as-is.
* for ((param, value) : params) {
@@ -1758,25 +2193,26 @@ ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
* dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.
* pledgedSrcSize must be correct.
* If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t
-ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
const void* dict, size_t dictSize,
ZSTD_parameters params,
unsigned long long pledgedSrcSize);
-/**! ZSTD_initCStream_usingCDict() :
- * This function is deprecated, and equivalent to:
+/*! ZSTD_initCStream_usingCDict() :
+ * This function is DEPRECATED, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, cdict);
- *
+ *
* note : cdict will just be referenced, and must outlive compression session
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
-/**! ZSTD_initCStream_usingCDict_advanced() :
+/*! ZSTD_initCStream_usingCDict_advanced() :
* This function is DEPRECATED, and is approximately equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* // Pseudocode: Set each zstd frame parameter and leave the rest as-is.
@@ -1789,18 +2225,21 @@ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDi
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
* value ZSTD_CONTENTSIZE_UNKNOWN.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t
-ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
const ZSTD_CDict* cdict,
ZSTD_frameParameters fParams,
unsigned long long pledgedSrcSize);
/*! ZSTD_resetCStream() :
- * This function is deprecated, and is equivalent to:
+ * This function is DEPRECATED, and is equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but
+ * ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be
+ * explicitly specified.
*
* start a new frame, using same parameters from previous frame.
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
@@ -1810,9 +2249,10 @@ ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
* For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
* but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
* @return : 0, or an error code (which can be tested using ZSTD_isError())
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ * This prototype will generate compilation warnings.
*/
-ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
typedef struct {
@@ -1849,7 +2289,8 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
/*===== Advanced Streaming decompression functions =====*/
-/**
+
+/*!
* This function is deprecated, and is equivalent to:
*
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
@@ -1860,7 +2301,7 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
*/
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
-/**
+/*!
* This function is deprecated, and is equivalent to:
*
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
@@ -1871,7 +2312,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dic
*/
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
-/**
+/*!
* This function is deprecated, and is equivalent to:
*
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
@@ -1898,8 +2339,7 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
Start by initializing a context.
- Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression,
- or ZSTD_compressBegin_advanced(), for finer parameter control.
+ Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.
It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
Then, consume your input using ZSTD_compressContinue().
@@ -1924,16 +2364,18 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
/*===== Buffer-less streaming compression functions =====*/
ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
-ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-
-/*-
+/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */
+ZSTD_DEPRECATED("use advanced API to access custom parameters")
+size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
+ZSTD_DEPRECATED("use advanced API to access custom parameters")
+size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
+/**
Buffer-less streaming decompression (synchronous mode)
A ZSTD_DCtx object is required to track streaming operations.
diff --git a/Utilities/cmzstd/lib/common/zstd_errors.h b/Utilities/cmzstd/lib/zstd_errors.h
index 998398e7e..fa3686b77 100644
--- a/Utilities/cmzstd/lib/common/zstd_errors.h
+++ b/Utilities/cmzstd/lib/zstd_errors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the BSD-style license (found in the
@@ -77,6 +77,7 @@ typedef enum {
ZSTD_error_frameIndex_tooLarge = 100,
ZSTD_error_seekableIO = 102,
ZSTD_error_dstBuffer_wrong = 104,
+ ZSTD_error_srcBuffer_wrong = 105,
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
} ZSTD_ErrorCode;
diff --git a/bootstrap b/bootstrap
index c7fbed11c..a487375ae 100755
--- a/bootstrap
+++ b/bootstrap
@@ -325,6 +325,7 @@ CMAKE_CXX_SOURCES="\
cmDefinePropertyCommand \
cmDefinitions \
cmDocumentationFormatter \
+ cmELF \
cmEnableLanguageCommand \
cmEnableTestingCommand \
cmExecProgramCommand \
@@ -426,6 +427,7 @@ CMAKE_CXX_SOURCES="\
cmPolicies \
cmProcessOutput \
cmProjectCommand \
+ cmValue \
cmPropertyDefinition \
cmPropertyMap \
cmGccDepfileLexerHelper \