summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml34
-rw-r--r--.gitlab/ci/configure_cuda9.2_nvidia.cmake3
-rw-r--r--.gitlab/ci/configure_debian10_aarch64_ninja.cmake1
-rw-r--r--.gitlab/ci/configure_debian10_ninja.cmake1
-rw-r--r--.gitlab/ci/configure_fedora34_makefiles.cmake1
-rw-r--r--.gitlab/ci/configure_hip4.2_radeon.cmake3
-rw-r--r--.gitlab/ci/docker/cuda9.2/Dockerfile5
-rwxr-xr-x.gitlab/ci/docker/cuda9.2/install_deps.sh14
-rw-r--r--.gitlab/ci/docker/hip4.2/Dockerfile7
-rwxr-xr-x.gitlab/ci/docker/hip4.2/install_deps.sh13
-rw-r--r--.gitlab/ci/env_cuda9.2_nvidia.sh4
-rw-r--r--.gitlab/os-linux.yml39
-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/ctest_submit.rst3
-rw-r--r--Help/command/ctest_test.rst47
-rw-r--r--Help/command/file.rst5
-rw-r--r--Help/command/find_package.rst49
-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/set_property.rst4
-rw-r--r--Help/command/source_group.rst3
-rw-r--r--Help/command/string.rst91
-rw-r--r--Help/cpack_gen/deb.rst30
-rw-r--r--Help/cpack_gen/nsis.rst10
-rw-r--r--Help/cpack_gen/rpm.rst15
-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/manual/cmake-env-variables.7.rst3
-rw-r--r--Help/manual/cmake-packages.7.rst6
-rw-r--r--Help/manual/cmake-policies.7.rst8
-rw-r--r--Help/manual/cmake-properties.7.rst2
-rw-r--r--Help/manual/cmake-variables.7.rst3
-rw-r--r--Help/policy/CMP0127.rst32
-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.rst33
-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/Fortran_BUILDING_INSTRINSIC_MODULES.rst14
-rw-r--r--Help/prop_tgt/LINK_WHAT_YOU_USE.rst24
-rw-r--r--Help/release/dev/0-sample-topic.rst7
-rw-r--r--Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst5
-rw-r--r--Help/release/dev/GoogleTest-gtest-filter.rst6
-rw-r--r--Help/release/dev/LINK_WHAT_USE_USE-configuration.rst5
-rw-r--r--Help/release/dev/UseSWIG-dependencies.rst6
-rw-r--r--Help/release/dev/cmake-install-mode-symlink.rst16
-rw-r--r--Help/release/dev/cmake_dependent_option_policy.rst6
-rw-r--r--Help/release/dev/cpack-deb-add-zstd-compression.rst6
-rw-r--r--Help/release/dev/cpack-rpm-requires-exclude-from.rst6
-rw-r--r--Help/release/dev/ctest-environment-modifications.rst7
-rw-r--r--Help/release/dev/ctest-runtime-labels.rst7
-rw-r--r--Help/release/dev/ctest_memcheck-generate-test.xml.rst6
-rw-r--r--Help/release/dev/env-init-configs.rst9
-rw-r--r--Help/release/dev/find-matlab-imported-targets.rst4
-rw-r--r--Help/release/dev/find_package-required-var.rst5
-rw-r--r--Help/release/dev/msvc-isystem.rst7
-rw-r--r--Help/release/dev/ninja-edit_cache.rst5
-rw-r--r--Help/release/dev/nsis-minimal-version.rst4
-rw-r--r--Help/release/dev/nsis_ignore_install_page.rst6
-rw-r--r--Help/release/dev/os-release.rst6
-rw-r--r--Help/release/dev/string-TIMESTAMP-specifier-V.rst5
-rw-r--r--Help/release/dev/target_compile_features-ignore-disabled-langs.rst5
-rw-r--r--Help/release/dev/vs10-deprecate.rst5
-rw-r--r--Help/release/dev/vs_settings.rst5
-rw-r--r--Help/release/index.rst2
-rw-r--r--Help/variable/CMAKE_BUILD_TYPE.rst9
-rw-r--r--Help/variable/CMAKE_CONFIGURATION_TYPES.rst6
-rw-r--r--Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst2
-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_LINK_WHAT_YOU_USE.rst2
-rw-r--r--Help/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK.rst10
-rw-r--r--Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst5
-rw-r--r--Help/variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName.rst14
-rw-r--r--Modules/CMakeASM_MASMInformation.cmake2
-rw-r--r--Modules/CMakeCInformation.cmake10
-rw-r--r--Modules/CMakeCUDAInformation.cmake9
-rw-r--r--Modules/CMakeCXXInformation.cmake9
-rw-r--r--Modules/CMakeDependentOption.cmake61
-rw-r--r--Modules/CMakeDetermineASMCompiler.cmake19
-rw-r--r--Modules/CMakeDetermineCUDACompiler.cmake19
-rw-r--r--Modules/CMakeDetermineCompilerId.cmake7
-rw-r--r--Modules/CMakeFindPackageMode.cmake2
-rw-r--r--Modules/CMakeFortranCompilerABI.F9048
-rw-r--r--Modules/CMakeFortranInformation.cmake9
-rw-r--r--Modules/CMakeHIPInformation.cmake9
-rw-r--r--Modules/CMakeOBJCInformation.cmake9
-rw-r--r--Modules/CMakeOBJCXXInformation.cmake9
-rw-r--r--Modules/CMakeSwiftInformation.cmake9
-rw-r--r--Modules/CMakeTestFortranCompiler.cmake9
-rw-r--r--Modules/CheckCXXSymbolExists.cmake2
-rw-r--r--Modules/CheckFortranFunctionExists.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/Clang-C.cmake1
-rw-r--r--Modules/Compiler/Clang-CXX.cmake1
-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.cmake7
-rw-r--r--Modules/Compiler/MSVC-CXX.cmake7
-rw-r--r--Modules/Compiler/PGI.cmake2
-rw-r--r--Modules/FetchContent.cmake452
-rw-r--r--Modules/FindBLAS.cmake67
-rw-r--r--Modules/FindCUDAToolkit.cmake7
-rw-r--r--Modules/FindFLTK.cmake12
-rw-r--r--Modules/FindGLUT.cmake163
-rw-r--r--Modules/FindICU.cmake4
-rw-r--r--Modules/FindLAPACK.cmake76
-rw-r--r--Modules/FindMPI.cmake54
-rw-r--r--Modules/FindMPI/test_mpi.c18
-rw-r--r--Modules/FindMatlab.cmake53
-rw-r--r--Modules/FindPatch.cmake2
-rw-r--r--Modules/FindPkgConfig.cmake52
-rw-r--r--Modules/FindThreads.cmake2
-rw-r--r--Modules/FindX11.cmake6
-rw-r--r--Modules/GNUInstallDirs.cmake37
-rw-r--r--Modules/GoogleTest.cmake11
-rw-r--r--Modules/GoogleTestAddTests.cmake11
-rw-r--r--Modules/InstallRequiredSystemLibraries.cmake33
-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/UseSWIG.cmake25
-rw-r--r--Modules/VTKCompatibility.cmake4
-rw-r--r--Source/CMakeLists.txt42
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.cxx10
-rw-r--r--Source/CPack/IFW/cmCPackIFWCommon.h4
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx59
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx112
-rw-r--r--Source/CPack/IFW/cmCPackIFWPackage.cxx96
-rw-r--r--Source/CPack/IFW/cmCPackIFWRepository.cxx25
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx87
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx20
-rw-r--r--Source/CPack/cmCPackBundleGenerator.cxx47
-rw-r--r--Source/CPack/cmCPackCygwinBinaryGenerator.cxx8
-rw-r--r--Source/CPack/cmCPackCygwinSourceGenerator.cxx15
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx506
-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.cxx217
-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/CTest/cmCTestGenericHandler.cxx30
-rw-r--r--Source/CTest/cmCTestGenericHandler.h13
-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.cxx182
-rw-r--r--Source/CTest/cmCTestRunTest.h3
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx8
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx12
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx21
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx20
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx235
-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/LexerParser/cmFortranParser.cxx78
-rw-r--r--Source/LexerParser/cmFortranParser.y4
-rw-r--r--Source/QtDialog/QCMake.cxx21
-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/cmCMakeHostSystemInformationCommand.cxx606
-rw-r--r--Source/cmCMakePolicyCommand.cxx1
-rw-r--r--Source/cmCPluginAPI.cxx2
-rw-r--r--Source/cmCacheManager.cxx20
-rw-r--r--Source/cmCacheManager.h18
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx2
-rw-r--r--Source/cmCommonTargetGenerator.cxx6
-rw-r--r--Source/cmCommonTargetGenerator.h6
-rw-r--r--Source/cmComputeLinkDepends.cxx2
-rw-r--r--Source/cmComputeLinkInformation.cxx7
-rw-r--r--Source/cmComputeLinkInformation.h3
-rw-r--r--Source/cmComputeTargetDepends.cxx2
-rw-r--r--Source/cmConditionEvaluator.cxx971
-rw-r--r--Source/cmConditionEvaluator.h30
-rw-r--r--Source/cmConfigure.cmake.h.in1
-rw-r--r--Source/cmCoreTryCompile.cxx10
-rw-r--r--Source/cmCurl.cxx42
-rw-r--r--Source/cmCurl.h1
-rw-r--r--Source/cmDefinitions.cxx6
-rw-r--r--Source/cmDefinitions.h4
-rw-r--r--Source/cmDependsFortran.cxx17
-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/cmExportFileGenerator.cxx52
-rw-r--r--Source/cmExportFileGenerator.h37
-rw-r--r--Source/cmExportInstallFileGenerator.cxx15
-rw-r--r--Source/cmExportInstallFileGenerator.h8
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmExportTryCompileFileGenerator.h5
-rw-r--r--Source/cmFileAPICodemodel.cxx3
-rw-r--r--Source/cmFileCommand.cxx61
-rw-r--r--Source/cmFileCopier.h5
-rw-r--r--Source/cmFileInstaller.cxx118
-rw-r--r--Source/cmFileInstaller.h5
-rw-r--r--Source/cmFindBase.cxx8
-rw-r--r--Source/cmFindLibraryCommand.cxx35
-rw-r--r--Source/cmFindPackageCommand.cxx24
-rw-r--r--Source/cmForEachCommand.cxx1
-rw-r--r--Source/cmFortranParser.h5
-rw-r--r--Source/cmFortranParserImpl.cxx13
-rw-r--r--Source/cmGeneratorExpressionNode.cxx8
-rw-r--r--Source/cmGeneratorTarget.cxx250
-rw-r--r--Source/cmGeneratorTarget.h22
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx11
-rw-r--r--Source/cmGetPropertyCommand.cxx24
-rw-r--r--Source/cmGetTestPropertyCommand.cxx5
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx2
-rw-r--r--Source/cmGlobalCommonGenerator.cxx34
-rw-r--r--Source/cmGlobalCommonGenerator.h5
-rw-r--r--Source/cmGlobalGenerator.cxx65
-rw-r--r--Source/cmGlobalGenerator.h5
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx3
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx2
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx81
-rw-r--r--Source/cmGlobalNinjaGenerator.h4
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx30
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx6
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx35
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h3
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx6
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx23
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx5
-rw-r--r--Source/cmIncludeGuardCommand.cxx1
-rw-r--r--Source/cmIncludeRegularExpressionCommand.cxx2
-rw-r--r--Source/cmInstallCommand.cxx5
-rw-r--r--Source/cmInstallMode.h17
-rw-r--r--Source/cmListFileCache.cxx4
-rw-r--r--Source/cmLocalGenerator.cxx139
-rw-r--r--Source/cmLocalGenerator.h6
-rw-r--r--Source/cmLocalNinjaGenerator.cxx2
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx6
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx13
-rw-r--r--Source/cmLocalVisualStudioGenerator.h6
-rw-r--r--Source/cmMakefile.cxx137
-rw-r--r--Source/cmMakefile.h40
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx23
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx25
-rw-r--r--Source/cmMakefileTargetGenerator.cxx34
-rw-r--r--Source/cmMarkAsAdvancedCommand.cxx1
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx39
-rw-r--r--Source/cmNinjaTargetGenerator.cxx35
-rw-r--r--Source/cmOptionCommand.cxx4
-rw-r--r--Source/cmPolicies.cxx1
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Source/cmProperty.cxx113
-rw-r--r--Source/cmProperty.h213
-rw-r--r--Source/cmPropertyMap.cxx11
-rw-r--r--Source/cmPropertyMap.h5
-rw-r--r--Source/cmQTWrapCPPCommand.cxx3
-rw-r--r--Source/cmQtAutoGenGlobalInitializer.cxx2
-rw-r--r--Source/cmQtAutoGenInitializer.cxx3
-rw-r--r--Source/cmSeparateArgumentsCommand.cxx3
-rw-r--r--Source/cmSetDirectoryPropertiesCommand.cxx2
-rw-r--r--Source/cmSetPropertyCommand.cxx10
-rw-r--r--Source/cmSetSourceFilesPropertiesCommand.cxx2
-rw-r--r--Source/cmSetTestsPropertiesCommand.cxx2
-rw-r--r--Source/cmSourceFile.cxx26
-rw-r--r--Source/cmSourceFile.h8
-rw-r--r--Source/cmStandardLevelResolver.cxx36
-rw-r--r--Source/cmStandardLevelResolver.h4
-rw-r--r--Source/cmState.cxx62
-rw-r--r--Source/cmState.h41
-rw-r--r--Source/cmStateDirectory.cxx232
-rw-r--r--Source/cmStateDirectory.h57
-rw-r--r--Source/cmStatePrivate.h15
-rw-r--r--Source/cmStateSnapshot.cxx32
-rw-r--r--Source/cmStateSnapshot.h3
-rw-r--r--Source/cmStringAlgorithms.cxx70
-rw-r--r--Source/cmStringAlgorithms.h107
-rw-r--r--Source/cmSystemTools.cxx245
-rw-r--r--Source/cmSystemTools.h11
-rw-r--r--Source/cmTarget.cxx388
-rw-r--r--Source/cmTarget.h54
-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/cmTargetLinkOptionsCommand.cxx2
-rw-r--r--Source/cmTargetPropertyComputer.h6
-rw-r--r--Source/cmTest.cxx10
-rw-r--r--Source/cmTest.h8
-rw-r--r--Source/cmTimestamp.cxx23
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx103
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h14
-rw-r--r--Source/cmWhileCommand.cxx89
-rw-r--r--Source/cmake.cxx88
-rw-r--r--Source/cmake.h21
-rw-r--r--Source/cmcmd.cxx11
-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--Tests/CMakeLists.txt59
-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.txt35
-rw-r--r--Tests/Environment/check_mod.cmake55
-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/FindMatlab/targets_checks/CMakeLists.txt44
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt24
-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/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.txt7
-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/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.cmake27
-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-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/RunCMakeTest.cmake14
-rw-r--r--Tests/RunCMake/GoogleTest/fake_gtest.cpp55
-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/UseSWIG/CMP0086-OLD-stderr.txt10
-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.cmake17
-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/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-RPATH/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.txt2
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/IWYU/mapping.imp1
-rw-r--r--Utilities/KWIML/include/kwiml/int.h17
-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/Sphinx/CMakeLists.txt2
-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.h6
-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.c9
-rw-r--r--Utilities/cmcurl/lib/http.c279
-rw-r--r--Utilities/cmcurl/lib/http.h3
-rw-r--r--Utilities/cmcurl/lib/http2.c195
-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.c152
-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.h4
-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.c5
-rw-r--r--Utilities/cmcurl/lib/telnet.c33
-rw-r--r--Utilities/cmcurl/lib/tftp.c40
-rw-r--r--Utilities/cmcurl/lib/transfer.c66
-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/.gitattributes1
-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/src/win/process.c5
-rwxr-xr-xbootstrap2
753 files changed, 18108 insertions, 10165 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2ead13b..a964b46 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -52,7 +52,7 @@ prep:doc-package:
- .cmake_doc_artifacts
- .run_only_for_package
-.upload:source-package:
+upload:source-package:
extends:
- .rsync_upload_binary
- .run_only_for_package
@@ -70,7 +70,7 @@ build:help:master:
- .cmake_org_help
- .run_only_for_continuous_master
-.upload:help:master:
+upload:help:master:
extends:
- .rsync_upload_help
- .run_only_for_continuous_master
@@ -86,7 +86,7 @@ build:help:stage:
- .cmake_org_help
- .run_only_for_continuous_stage
-.upload:help:stage:
+upload:help:stage:
extends:
- .rsync_upload_help
- .run_only_for_continuous_stage
@@ -219,6 +219,16 @@ test:fedora34-makefiles-nospace:
CMAKE_CI_BUILD_NAME: fedora34_makefiles_nospace
CMAKE_CI_JOB_NIGHTLY: "true"
+test:cuda9.2-nvidia:
+ extends:
+ - .cuda9.2_nvidia
+ - .cmake_test_linux_release
+ - .linux_builder_tags_cuda
+ - .run_dependent
+ - .needs_centos6_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
test:cuda10.2-nvidia:
extends:
- .cuda10.2_nvidia
@@ -238,6 +248,16 @@ test:cuda10.2-clang:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
+test:hip4.2-radeon:
+ extends:
+ - .hip4.2_radeon
+ - .cmake_test_linux_release
+ - .linux_builder_tags_radeon
+ - .run_dependent
+ - .needs_centos6_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
build:fedora34-ninja:
extends:
- .fedora34_ninja
@@ -500,7 +520,7 @@ build:linux-x86_64-package:
needs:
- prep:doc-package
-.upload:linux-x86_64-package:
+upload:linux-x86_64-package:
extends:
- .rsync_upload_binary
- .run_only_for_package
@@ -524,7 +544,7 @@ build:linux-aarch64-package:
needs:
- prep:doc-package
-.upload:linux-aarch64-package:
+upload:linux-aarch64-package:
extends:
- .rsync_upload_binary
- .run_only_for_package
@@ -663,7 +683,7 @@ build:macos-package:
needs:
- prep:doc-package
-.upload:macos-package:
+upload:macos-package:
extends:
- .rsync_upload_binary
- .run_only_for_package
@@ -686,7 +706,7 @@ build:macos10.10-package:
needs:
- prep:doc-package
-.upload:macos10.10-package:
+upload:macos10.10-package:
extends:
- .rsync_upload_binary
- .run_only_for_package
diff --git a/.gitlab/ci/configure_cuda9.2_nvidia.cmake b/.gitlab/ci/configure_cuda9.2_nvidia.cmake
new file mode 100644
index 0000000..519699b
--- /dev/null
+++ b/.gitlab/ci/configure_cuda9.2_nvidia.cmake
@@ -0,0 +1,3 @@
+set(CMake_TEST_CUDA "NVIDIA" CACHE STRING "")
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
index 4d8dde6..a6b7cb5 100644
--- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
+++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
@@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "")
set(CMake_TEST_FindGIF "ON" CACHE BOOL "")
set(CMake_TEST_FindGit "ON" CACHE BOOL "")
set(CMake_TEST_FindGLEW "ON" CACHE BOOL "")
+set(CMake_TEST_FindGLUT "ON" CACHE BOOL "")
set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "")
set(CMake_TEST_FindGSL "ON" CACHE BOOL "")
set(CMake_TEST_FindGTest "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake
index 732624a..10d0997 100644
--- a/.gitlab/ci/configure_debian10_ninja.cmake
+++ b/.gitlab/ci/configure_debian10_ninja.cmake
@@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "")
set(CMake_TEST_FindGIF "ON" CACHE BOOL "")
set(CMake_TEST_FindGit "ON" CACHE BOOL "")
set(CMake_TEST_FindGLEW "ON" CACHE BOOL "")
+set(CMake_TEST_FindGLUT "ON" CACHE BOOL "")
set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "")
set(CMake_TEST_FindGSL "ON" CACHE BOOL "")
set(CMake_TEST_FindGTest "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_fedora34_makefiles.cmake b/.gitlab/ci/configure_fedora34_makefiles.cmake
index 48786e4..d4bdb6a 100644
--- a/.gitlab/ci/configure_fedora34_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora34_makefiles.cmake
@@ -16,6 +16,7 @@ set(CMake_TEST_FindGDAL "ON" CACHE BOOL "")
set(CMake_TEST_FindGIF "ON" CACHE BOOL "")
set(CMake_TEST_FindGit "ON" CACHE BOOL "")
set(CMake_TEST_FindGLEW "ON" CACHE BOOL "")
+set(CMake_TEST_FindGLUT "ON" CACHE BOOL "")
set(CMake_TEST_FindGnuTLS "ON" CACHE BOOL "")
set(CMake_TEST_FindGSL "ON" CACHE BOOL "")
set(CMake_TEST_FindGTest "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_hip4.2_radeon.cmake b/.gitlab/ci/configure_hip4.2_radeon.cmake
new file mode 100644
index 0000000..58036b0
--- /dev/null
+++ b/.gitlab/ci/configure_hip4.2_radeon.cmake
@@ -0,0 +1,3 @@
+set(CMake_TEST_HIP "ON" CACHE BOOL "")
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/docker/cuda9.2/Dockerfile b/.gitlab/ci/docker/cuda9.2/Dockerfile
new file mode 100644
index 0000000..7eae886
--- /dev/null
+++ b/.gitlab/ci/docker/cuda9.2/Dockerfile
@@ -0,0 +1,5 @@
+FROM nvidia/cuda:9.2-devel-ubuntu16.04
+MAINTAINER Brad King <brad.king@kitware.com>
+
+COPY install_deps.sh /root/install_deps.sh
+RUN sh /root/install_deps.sh
diff --git a/.gitlab/ci/docker/cuda9.2/install_deps.sh b/.gitlab/ci/docker/cuda9.2/install_deps.sh
new file mode 100755
index 0000000..146f982
--- /dev/null
+++ b/.gitlab/ci/docker/cuda9.2/install_deps.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+apt-get update
+
+# Install development tools.
+apt-get install -y \
+ g++ \
+ clang-3.8 \
+ curl \
+ git
+
+apt-get clean
diff --git a/.gitlab/ci/docker/hip4.2/Dockerfile b/.gitlab/ci/docker/hip4.2/Dockerfile
new file mode 100644
index 0000000..563e94f
--- /dev/null
+++ b/.gitlab/ci/docker/hip4.2/Dockerfile
@@ -0,0 +1,7 @@
+FROM rocm/dev-ubuntu-20.04:4.2
+MAINTAINER Brad King <brad.king@kitware.com>
+
+ENV PATH="/opt/rocm/bin:$PATH"
+
+COPY install_deps.sh /root/install_deps.sh
+RUN sh /root/install_deps.sh
diff --git a/.gitlab/ci/docker/hip4.2/install_deps.sh b/.gitlab/ci/docker/hip4.2/install_deps.sh
new file mode 100755
index 0000000..2b45bc9
--- /dev/null
+++ b/.gitlab/ci/docker/hip4.2/install_deps.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+apt-get update
+
+# Install development tools.
+apt-get install -y --no-install-recommends \
+ g++ \
+ curl \
+ git
+
+apt-get clean
diff --git a/.gitlab/ci/env_cuda9.2_nvidia.sh b/.gitlab/ci/env_cuda9.2_nvidia.sh
new file mode 100644
index 0000000..16bfba4
--- /dev/null
+++ b/.gitlab/ci/env_cuda9.2_nvidia.sh
@@ -0,0 +1,4 @@
+export CC=/usr/bin/clang-3.8
+export CXX=/usr/bin/clang++-3.8
+export CUDAHOSTCXX=/usr/bin/g++-5
+export CUDACXX=/usr/local/cuda/bin/nvcc
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 95cab05..1513c90 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -208,6 +208,21 @@
### CUDA builds
+.cuda9.2:
+ image: "kitware/cmake:ci-cuda9.2-x86_64-2021-07-01"
+
+ variables:
+ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+ CMAKE_ARCH: x86_64
+ CTEST_LABELS: "CUDA"
+
+.cuda9.2_nvidia:
+ extends: .cuda9.2
+
+ variables:
+ CMAKE_CONFIGURATION: cuda9.2_nvidia
+ CMAKE_GENERATOR: "Ninja Multi-Config"
+
.cuda10.2:
image: "kitware/cmake:ci-cuda10.2-x86_64-2021-06-16"
@@ -230,6 +245,23 @@
CMAKE_CONFIGURATION: cuda10.2_clang
CTEST_NO_WARNINGS_ALLOWED: 1
+### HIP builds
+
+.hip4.2:
+ image: "kitware/cmake:ci-hip4.2-x86_64-2021-07-09"
+
+ variables:
+ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+ CMAKE_ARCH: x86_64
+ CTEST_LABELS: "HIP"
+
+.hip4.2_radeon:
+ extends: .hip4.2
+
+ variables:
+ CMAKE_CONFIGURATION: hip4.2_radeon
+ CMAKE_GENERATOR: "Ninja Multi-Config"
+
## Tags
.linux_builder_tags:
@@ -262,6 +294,13 @@
- docker
- linux
+.linux_builder_tags_radeon:
+ tags:
+ - cmake
+ - radeon
+ - docker
+ - linux
+
.linux_builder_tags_aarch64:
tags:
- cmake
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index d2a04fe..7a3e4ed 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 9944ea4..fdfe456 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 2b902a9..998e146 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/ctest_submit.rst b/Help/command/ctest_submit.rst
index e6d277f..d661825 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 89787d1..4e5484f 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -190,29 +190,33 @@ 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.
+Starting in version 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 +226,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
@@ -257,8 +261,10 @@ 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
@@ -274,3 +280,18 @@ The following example demonstrates how to specify a custom value for the
std::cout <<
"<CTestDetails>My Custom Details Value</CTestDetails>" << std::endl;
+
+Additional Labels
+"""""""""""""""""
+
+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 f038871..96a55ee 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -843,6 +843,11 @@ 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
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 3dfd62f..8388709 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -28,11 +28,26 @@ 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 +55,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.
@@ -432,7 +448,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 +464,15 @@ 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.
Package File Interface Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -479,7 +502,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 f77d8af..46da285 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 fbf3e36..6ff8852 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 c6af489..1236f1d 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/set_property.rst b/Help/command/set_property.rst
index bf437b4..555520d 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 a4b5bf1..83ae286 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 8ad0089..29ad082 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/cpack_gen/deb.rst b/Help/cpack_gen/deb.rst
index d8d53ec..f96ca32 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 02e33ba..299cfec 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 322ab68..823594a 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
@@ -1035,3 +1039,14 @@ 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
+
+ * 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/envvar/CMAKE_BUILD_TYPE.rst b/Help/envvar/CMAKE_BUILD_TYPE.rst
new file mode 100644
index 0000000..f798aff
--- /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 0000000..833aa4a
--- /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 0000000..37db0d7
--- /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 c065550..9ec33c3 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/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index fa38588..0799fdd 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-packages.7.rst b/Help/manual/cmake-packages.7.rst
index 4b2934a..5c109ff 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 b9e3d45..0f0c0ab 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,14 @@ 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
+
+ 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 5f18a82..c71e8ff 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
@@ -450,6 +451,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 9cea0fb..7cfa0c8 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -231,6 +231,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
@@ -428,6 +429,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 +440,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
diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst
new file mode 100644
index 0000000..8560bbf
--- /dev/null
+++ b/Help/policy/CMP0127.rst
@@ -0,0 +1,32 @@
+CMP0127
+-------
+
+: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/prop_sf/VS_SETTINGS.rst b/Help/prop_sf/VS_SETTINGS.rst
index 322f5a6..871e36e 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 102c792..43bcdbe 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 0000000..ffd5de4
--- /dev/null
+++ b/Help/prop_test/ENVIRONMENT_MODIFICATION.rst
@@ -0,0 +1,33 @@
+ENVIRONMENT_MODIFICATION
+------------------------
+
+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``. 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_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index 52d96e0..ed8b262 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 9a98f44..0a0c2a1 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 cd24f5e..e0cea97 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/Fortran_BUILDING_INSTRINSIC_MODULES.rst b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst
new file mode 100644
index 0000000..518bca7
--- /dev/null
+++ b/Help/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES.rst
@@ -0,0 +1,14 @@
+Fortran_BUILDING_INSTRINSIC_MODULES
+-----------------------------------
+
+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/LINK_WHAT_YOU_USE.rst b/Help/prop_tgt/LINK_WHAT_YOU_USE.rst
index 2ed93ad..d6de0d4 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/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+ Developers should add similar notes for each topic branch
+ making a noteworthy change. Each document should be named
+ and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst b/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst
new file mode 100644
index 0000000..44c26b5
--- /dev/null
+++ b/Help/release/dev/FindPkgConfig-PKG_CONFIG-args.rst
@@ -0,0 +1,5 @@
+FindPkgConfig-PKG_CONFIG-args
+-----------------------------
+
+* The :module:`FindPkgConfig` module gained a :variable:`PKG_CONFIG_ARGN`
+ variable to specify arguments to ``pkg-config`` calls.
diff --git a/Help/release/dev/GoogleTest-gtest-filter.rst b/Help/release/dev/GoogleTest-gtest-filter.rst
new file mode 100644
index 0000000..48b97a7
--- /dev/null
+++ b/Help/release/dev/GoogleTest-gtest-filter.rst
@@ -0,0 +1,6 @@
+GoogleTest-gtest-filter
+-----------------------
+
+* The :module:`GoogleTest` module :command:`gtest_discover_tests`
+ function gained a ``TEST_FILTER`` option to filter tests using
+ ``--gtest_filter`` during test discovery.
diff --git a/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst b/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst
new file mode 100644
index 0000000..990ed36
--- /dev/null
+++ b/Help/release/dev/LINK_WHAT_USE_USE-configuration.rst
@@ -0,0 +1,5 @@
+LINK_WHAT_YOU_USE-configuration
+-------------------------------
+
+* Configuration for :prop_tgt:`LINK_WHAT_YOU_USE` feature is now controlled by
+ ``CMake`` variables and only active for ``ELF`` platforms.
diff --git a/Help/release/dev/UseSWIG-dependencies.rst b/Help/release/dev/UseSWIG-dependencies.rst
new file mode 100644
index 0000000..a3ec29e
--- /dev/null
+++ b/Help/release/dev/UseSWIG-dependencies.rst
@@ -0,0 +1,6 @@
+UseSWIG-dependencies
+--------------------
+
+* :module:`UseSWIG` module gained the capability, for
+ :ref:`Visual Studio Generators` to use `swig` tool to generate implicit
+ dependencies.
diff --git a/Help/release/dev/cmake-install-mode-symlink.rst b/Help/release/dev/cmake-install-mode-symlink.rst
new file mode 100644
index 0000000..a5f75ca
--- /dev/null
+++ b/Help/release/dev/cmake-install-mode-symlink.rst
@@ -0,0 +1,16 @@
+cmake-install-mode-symlink
+--------------------------
+
+* The :envvar:`CMAKE_INSTALL_MODE` environment variable was added to
+ allow users to override the default file-copying behavior of
+ :command:`install` and :command:`file(INSTALL)` into creating
+ symbolic links. This can aid in lowering storage space requirements
+ and avoiding redundancy.
+
+* The :command:`file(INSTALL)` can now be affected / modified by the
+ :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation
+ of symbolic links instead of copying of files.
+
+* The :command:`install` can now be affected / modified by the
+ :envvar:`CMAKE_INSTALL_MODE` environment variable causing installation
+ of symbolic links instead of copying of files.
diff --git a/Help/release/dev/cmake_dependent_option_policy.rst b/Help/release/dev/cmake_dependent_option_policy.rst
new file mode 100644
index 0000000..c131170
--- /dev/null
+++ b/Help/release/dev/cmake_dependent_option_policy.rst
@@ -0,0 +1,6 @@
+cmake_dependent_option_policy
+-----------------------------
+
+* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option`
+ macro now supports full :ref:`Condition Syntax`.
+ See policy :policy:`CMP0127`.
diff --git a/Help/release/dev/cpack-deb-add-zstd-compression.rst b/Help/release/dev/cpack-deb-add-zstd-compression.rst
new file mode 100644
index 0000000..a138455
--- /dev/null
+++ b/Help/release/dev/cpack-deb-add-zstd-compression.rst
@@ -0,0 +1,6 @@
+cpack-deb-add-zstd-compression
+------------------------------
+
+* 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.
diff --git a/Help/release/dev/cpack-rpm-requires-exclude-from.rst b/Help/release/dev/cpack-rpm-requires-exclude-from.rst
new file mode 100644
index 0000000..7125901
--- /dev/null
+++ b/Help/release/dev/cpack-rpm-requires-exclude-from.rst
@@ -0,0 +1,6 @@
+cpack-rpm-requires-exclude-from
+-------------------------------
+
+* The :cpack_gen:`CPack RPM Generator` gained the
+ :variable:`CPACK_RPM_REQUIRES_EXCLUDE_FROM` option avoid scanning
+ specific paths for dependencies.
diff --git a/Help/release/dev/ctest-environment-modifications.rst b/Help/release/dev/ctest-environment-modifications.rst
new file mode 100644
index 0000000..64265f0
--- /dev/null
+++ b/Help/release/dev/ctest-environment-modifications.rst
@@ -0,0 +1,7 @@
+ctest-environment-modifications
+-------------------------------
+
+* :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.
diff --git a/Help/release/dev/ctest-runtime-labels.rst b/Help/release/dev/ctest-runtime-labels.rst
new file mode 100644
index 0000000..7ce0b64
--- /dev/null
+++ b/Help/release/dev/ctest-runtime-labels.rst
@@ -0,0 +1,7 @@
+ctest-runtime-labels
+--------------------
+
+* :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.
diff --git a/Help/release/dev/ctest_memcheck-generate-test.xml.rst b/Help/release/dev/ctest_memcheck-generate-test.xml.rst
new file mode 100644
index 0000000..fac02d8
--- /dev/null
+++ b/Help/release/dev/ctest_memcheck-generate-test.xml.rst
@@ -0,0 +1,6 @@
+ctest_memcheck-generate-test.xml
+--------------------------------
+
+* The :command:`ctest_memcheck` command now also generates a
+ `DynamicAnalysis-Test.xml` file which may be used to submit test results to
+ CDash.
diff --git a/Help/release/dev/env-init-configs.rst b/Help/release/dev/env-init-configs.rst
new file mode 100644
index 0000000..5c9892d
--- /dev/null
+++ b/Help/release/dev/env-init-configs.rst
@@ -0,0 +1,9 @@
+env-init-configs
+----------------
+
+* 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.
diff --git a/Help/release/dev/find-matlab-imported-targets.rst b/Help/release/dev/find-matlab-imported-targets.rst
new file mode 100644
index 0000000..33a93ff
--- /dev/null
+++ b/Help/release/dev/find-matlab-imported-targets.rst
@@ -0,0 +1,4 @@
+find-matlab-imported-targets
+----------------------------
+
+* The :module:`FindMatlab` module now provides imported targets.
diff --git a/Help/release/dev/find_package-required-var.rst b/Help/release/dev/find_package-required-var.rst
new file mode 100644
index 0000000..36935ef
--- /dev/null
+++ b/Help/release/dev/find_package-required-var.rst
@@ -0,0 +1,5 @@
+find_package-required-var
+-------------------------
+
+* The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable was added
+ to turn a non-REQUIRED :command:`find_package` call into a REQUIRED one.
diff --git a/Help/release/dev/msvc-isystem.rst b/Help/release/dev/msvc-isystem.rst
new file mode 100644
index 0000000..4a5d79f
--- /dev/null
+++ b/Help/release/dev/msvc-isystem.rst
@@ -0,0 +1,7 @@
+msvc-isystem
+------------
+
+* The MSVC compilers learned to pass the ``-external:I`` flag for system
+ includes when using the :generator:`Ninja` and :generator:`NMake Makefiles`
+ generators. This became available as of Visual Studio 16.10 (toolchain
+ version 14.29.30037).
diff --git a/Help/release/dev/ninja-edit_cache.rst b/Help/release/dev/ninja-edit_cache.rst
new file mode 100644
index 0000000..9083f56
--- /dev/null
+++ b/Help/release/dev/ninja-edit_cache.rst
@@ -0,0 +1,5 @@
+ninja-edit_cache
+----------------
+
+* The :ref:`Ninja Generators` now implement the ``edit_cache`` target
+ using :manual:`ccmake(1)` if available.
diff --git a/Help/release/dev/nsis-minimal-version.rst b/Help/release/dev/nsis-minimal-version.rst
new file mode 100644
index 0000000..b19597a
--- /dev/null
+++ b/Help/release/dev/nsis-minimal-version.rst
@@ -0,0 +1,4 @@
+nsis-minimal-version.rst
+------------------------
+
+* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.03 or later.
diff --git a/Help/release/dev/nsis_ignore_install_page.rst b/Help/release/dev/nsis_ignore_install_page.rst
new file mode 100644
index 0000000..2d8a8d0
--- /dev/null
+++ b/Help/release/dev/nsis_ignore_install_page.rst
@@ -0,0 +1,6 @@
+nsis_ignore_install_page
+------------------------
+
+* The :cpack_gen:`CPack NSIS Generator` gained a new variable
+ :variable:`CPACK_NSIS_IGNORE_LICENSE_PAGE` to ignore the
+ license page in the installer.
diff --git a/Help/release/dev/os-release.rst b/Help/release/dev/os-release.rst
new file mode 100644
index 0000000..cce6aee
--- /dev/null
+++ b/Help/release/dev/os-release.rst
@@ -0,0 +1,6 @@
+os-release
+----------
+
+* The :command:`cmake_host_system_information` command query operating system
+ identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_
+ from the :file:`/etc/os-release` file.
diff --git a/Help/release/dev/string-TIMESTAMP-specifier-V.rst b/Help/release/dev/string-TIMESTAMP-specifier-V.rst
new file mode 100644
index 0000000..afd3f03
--- /dev/null
+++ b/Help/release/dev/string-TIMESTAMP-specifier-V.rst
@@ -0,0 +1,5 @@
+string-TIMESTAMP-specifier-V
+----------------------------
+
+* The :command:`string(TIMESTAMP)` command now supports the ``%V``
+ specifier for ISO 8601 week numbers.
diff --git a/Help/release/dev/target_compile_features-ignore-disabled-langs.rst b/Help/release/dev/target_compile_features-ignore-disabled-langs.rst
new file mode 100644
index 0000000..0eba125
--- /dev/null
+++ b/Help/release/dev/target_compile_features-ignore-disabled-langs.rst
@@ -0,0 +1,5 @@
+target_compile_features-ignore-disabled-langs
+---------------------------------------------
+
+* :command:`target_compile_features` learned to ignored features for languages that
+ aren't enabled.
diff --git a/Help/release/dev/vs10-deprecate.rst b/Help/release/dev/vs10-deprecate.rst
new file mode 100644
index 0000000..7bec391
--- /dev/null
+++ b/Help/release/dev/vs10-deprecate.rst
@@ -0,0 +1,5 @@
+vs10-deprecate
+--------------
+
+* The :generator:`Visual Studio 10 2010` generator is now deprecated
+ and will be removed in a future version of CMake.
diff --git a/Help/release/dev/vs_settings.rst b/Help/release/dev/vs_settings.rst
new file mode 100644
index 0000000..64f3ced
--- /dev/null
+++ b/Help/release/dev/vs_settings.rst
@@ -0,0 +1,5 @@
+vs_settings
+-----------
+
+* The :prop_sf:`VS_SETTINGS` source file property is now supported for
+ all source file types. Previously it worked only for non-built sources.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 75667e5..5938878 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@ CMake Release Notes
This file should include the adjacent "dev.txt" file
in development versions but not in release versions.
+.. include:: dev.txt
+
Releases
========
diff --git a/Help/variable/CMAKE_BUILD_TYPE.rst b/Help/variable/CMAKE_BUILD_TYPE.rst
index 405f7d5..9ad1481 100644
--- a/Help/variable/CMAKE_BUILD_TYPE.rst
+++ b/Help/variable/CMAKE_BUILD_TYPE.rst
@@ -23,3 +23,12 @@ 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``.
+
+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.
+
+See :variable:`CMAKE_CONFIGURATION_TYPES` for specifying the configuration
+with multi-config generators.
diff --git a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
index 8fcc798..5298a72 100644
--- a/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
+++ b/Help/variable/CMAKE_CONFIGURATION_TYPES.rst
@@ -8,5 +8,11 @@ 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.
diff --git a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst
index ed60020..f77e939 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_LANG_IMPLICIT_LINK_DIRECTORIES.rst b/Help/variable/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES.rst
index e9e04be..081c4da 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 ec16477..0c25489 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 0000000..5004530
--- /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_LINK_WHAT_YOU_USE.rst b/Help/variable/CMAKE_LINK_WHAT_YOU_USE.rst
index 06b3aa8..bca4519 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 0000000..e626641
--- /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_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst
index b991db2..11dd194 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`.
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 0000000..893f1ae
--- /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/Modules/CMakeASM_MASMInformation.cmake b/Modules/CMakeASM_MASMInformation.cmake
index 6d1e174..656b75e 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/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake
index 6be1865..665f309 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/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index a2946f4..e9cfed6 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/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake
index 944d236..53abf37 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/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake
index 96855d2..b7c478f 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 e8b9db7..a1814b7 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/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
index e360d31..342425c 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")
diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake
index e933cf4..16243c7 100644
--- a/Modules/CMakeDetermineCompilerId.cmake
+++ b/Modules/CMakeDetermineCompilerId.cmake
@@ -722,7 +722,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
@@ -733,7 +733,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.
diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake
index 815dfc9..726e2a2 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/CMakeFortranCompilerABI.F90 b/Modules/CMakeFortranCompilerABI.F90
new file mode 100644
index 0000000..4a17153
--- /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 9a4ce63..0f71c6f 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/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake
index ec37e1c..9862f24 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/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake
index ac67d01..4c697da 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/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake
index 70e8579..a6d824f 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 8f0909c..ecad1d5 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 f25788d..579f83f 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/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index b4da4fa..7b13c3a 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 ad72e2f..8f1ca9d 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/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index f8ca584..48ee3c4 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 0a64a8a..01c4cea 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 5dfb401..045b783 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/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake
index cf493d7..1b765ad 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 98828e0..84b05d7 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/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake
index ead9069..9884b58 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 37f339a..7c9cca9 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 d69d064..d7346f6 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 9799888..cae1f11 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 9a5104b..4ba1eea 100644
--- a/Modules/Compiler/MSVC-C.cmake
+++ b/Modules/Compiler/MSVC-C.cmake
@@ -29,6 +29,7 @@ endif()
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")
# 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
@@ -63,3 +64,9 @@ endmacro()
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 f1c7450..9bb7722 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
@@ -79,3 +80,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/PGI.cmake b/Modules/Compiler/PGI.cmake
index 4f8b90b..d111be9 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/FetchContent.cmake b/Modules/FetchContent.cmake
index bd82a90..5ea8b2a 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,88 @@ 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:
+.. command:: FetchContent_MakeAvailable
-.. _`fetch-content-canonical-pattern`:
+ .. versionadded:: 3.14
-.. code-block:: cmake
+ .. code-block:: cmake
- # 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>)
+ 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:
- # Set custom variables, policies, etc.
- # ...
+ .. code-block:: cmake
- # Bring the populated content into the build
- add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR})
- endif()
+ # WRONG: Should declare all details first
+ FetchContent_Declare(uses_other ...)
+ FetchContent_MakeAvailable(uses_other)
+
+ FetchContent_Declare(other ...) # Will be ignored, uses_other beat us to it
+ FetchContent_MakeAvailable(other) # Would use details declared by 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.
+ .. 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 +263,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 +296,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 +319,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 +342,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 +352,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 +375,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 +388,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 +400,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:
-
- .. code-block:: cmake
-
- FetchContent_GetProperties(foobar)
- if(NOT foobar_POPULATED)
- FetchContent_Populate(foobar)
- ...
- endif()
+ :command:`FetchContent_MakeAvailable(name) <FetchContent_MakeAvailable>` or
+ :command:`FetchContent_Populate(name) <FetchContent_Populate>`.
- 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 +522,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
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 726ff75..a44af4d 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -109,7 +109,8 @@ BLAS/LAPACK Vendors
``Goto``
GotoBLAS
-``IBMESSL``
+``IBMESSL``, ``IBMESSL_SMP``
+
IBM Engineering and Scientific Subroutine Library
``Intel``
@@ -150,7 +151,7 @@ BLAS/LAPACK Vendors
``PhiPACK``
Portable High Performance ANSI C (PHiPAC)
-``SCSL``
+``SCSL``, ``SCSL_mp``
Scientific Computing Software Library
``SGIMATH``
@@ -386,6 +387,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()
@@ -439,7 +442,7 @@ if(BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All")
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 +504,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 +616,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 +632,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)
@@ -734,14 +738,14 @@ 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")
+ set(_blas_armpl_lib "armpl_ilp64")
else()
- set(BLAS_armpl_LIB "armpl_lp64")
+ set(_blas_armpl_lib "armpl_lp64")
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")
+ set(_blas_armpl_lib "${_blas_armpl_lib}_mp")
endif()
if(NOT BLAS_LIBRARIES)
@@ -750,13 +754,13 @@ if(BLA_VENDOR MATCHES "Arm" OR BLA_VENDOR STREQUAL "All")
BLAS
sgemm
""
- "${BLAS_armpl_LIB}"
+ "${_blas_armpl_lib}"
""
""
""
)
endif()
-
+ unset(_blas_armpl_lib)
endif()
# FLAME's blis library? (https://github.com/flame/blis)
@@ -859,19 +863,27 @@ 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(BLA_VENDOR MATCHES "_mp")
+ set(_blas_scsl_lib "${_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 +902,27 @@ 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")
+ set(_blas_essl_lib "${_blas_essl_lib}smp")
+ 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?
@@ -1087,11 +1106,11 @@ endif()
# Elbrus Math Library?
if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
- set(BLAS_EML_LIB "eml")
+ set(_blas_eml_lib "eml")
# Check for OpenMP support, VIA BLA_VENDOR of eml_mt
if(BLA_VENDOR MATCHES "_mt")
- set(BLAS_EML_LIB "${BLAS_EML_LIB}_mt")
+ set(_blas_eml_lib "${_blas_eml_lib}_mt")
endif()
if(NOT BLAS_LIBRARIES)
@@ -1100,13 +1119,13 @@ if(BLA_VENDOR MATCHES "EML" OR BLA_VENDOR STREQUAL "All")
BLAS
sgemm
""
- "${BLAS_EML_LIB}"
+ "${_blas_eml_lib}"
""
""
""
)
endif()
-
+ unset(_blas_eml_lib)
endif()
# Fujitsu SSL2 Library?
@@ -1163,3 +1182,5 @@ if(NOT BLA_F95)
endif()
_add_blas_target()
+unset(_blas_fphsa_req_var)
+unset(_BLAS_LIBRARIES)
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 89b8c99..92042d2 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -844,14 +844,17 @@ 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}")
+ 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 bab7256..d54d2f6 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 2770c60..dd0975d 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/FindICU.cmake b/Modules/FindICU.cmake
index 2bb49ad..1bae825 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/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index 3146e06..f36acfd 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -298,7 +298,7 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
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 +311,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 +350,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 +363,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 +388,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)
@@ -485,6 +491,30 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
)
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")
+
+ # Check for OpenMP support, VIA BLA_VENDOR of scs_mp
+ if(BLA_VENDOR MATCHES "_mp")
+ set(_lapack_scsl_lib "${_lapack_scsl_lib}_mp")
+ endif()
+
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "${_lapack_scsl_lib}"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ unset(_lapack_scsl_lib)
+ endif()
+
# BLAS in acml library?
if(BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
if(BLAS_LIBRARIES MATCHES ".+acml.+")
@@ -580,6 +610,30 @@ if(NOT LAPACK_NOT_FOUND_MESSAGE)
unset(_ssl2_suffix)
endif()
+ # LAPACK in IBM ESSL library?
+ if(NOT LAPACK_LIBRARIES
+ AND (BLA_VENDOR MATCHES "IBMESSL" OR BLA_VENDOR STREQUAL "All"))
+ set(_lapack_essl_lib "essl")
+
+ # Check for OpenMP support, VIA BLA_VENDOR of esslsmp
+ if(BLA_VENDOR MATCHES "_SMP")
+ set(_lapack_essl_lib "${_lapack_essl_lib}smp")
+ endif()
+
+ check_lapack_libraries(
+ LAPACK_LIBRARIES
+ LAPACK
+ cheev
+ ""
+ "${_lapack_essl_lib}"
+ ""
+ ""
+ ""
+ "${BLAS_LIBRARIES}"
+ )
+ unset(_lapack_essl_lib)
+ endif()
+
# NVHPC Library?
if(NOT LAPACK_LIBRARIES
AND (BLA_VENDOR MATCHES "NVHPC" OR BLA_VENDOR STREQUAL "All"))
@@ -646,3 +700,5 @@ if(LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES")
endif()
_add_lapack_target()
+unset(_lapack_fphsa_req_var)
+unset(_LAPACK_LIBRARIES)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index d8f0334..d4b4a34 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.
@@ -333,6 +333,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 +493,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 +1466,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,6 +1546,29 @@ 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)
@@ -1548,7 +1597,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 7c96d54..70d7e1d 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 c8df670..12a5fde 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1865,6 +1892,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 4108651..f4fe4a6 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 01ad5ac..4de5331 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -15,6 +15,8 @@ following variables will also be set:
if pkg-config executable was found
``PKG_CONFIG_EXECUTABLE``
pathname of the pkg-config program
+``PKG_CONFIG_ARGN``
+ list of arguments to pass to pkg-config
``PKG_CONFIG_VERSION_STRING``
version of pkg-config (since CMake 2.8.8)
@@ -29,13 +31,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 +54,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 +67,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 +117,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 +411,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 +426,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 +571,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)
@@ -900,6 +930,18 @@ Variables Affecting Behavior
.. versionadded:: 3.1
The ``PKG_CONFIG`` environment variable can be used as a hint.
+.. variable:: PKG_CONFIG_ARGN
+
+ .. versionadded:: 3.22
+
+ This can be set to a list of arguments to additionally pass to pkg-config
+ if needed. If not provided, it will be an empty string, however, if the
+ environment variable ``PKG_CONFIG`` is provided, this will be set to the
+ result of splitting the variable.
+
+ The ``PKG_CONFIG`` environment variable can be used to provide both
+ ``PKG_CONFIG_EXECUTABLE`` and ``PKG_CONFIG_ARGN``
+
.. variable:: PKG_CONFIG_USE_CMAKE_PREFIX_PATH
.. versionadded:: 3.1
diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake
index c6a3451..e4d6cf3 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 d480fc4..fd5ee53 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 ead55ca..1b9cfce 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -216,6 +216,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
@@ -237,11 +238,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}")
@@ -251,7 +275,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)
@@ -260,6 +285,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/GoogleTest.cmake b/Modules/GoogleTest.cmake
index 80d8e23..a483c03 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,12 @@ 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 to ``--gtest_filter`` argument during test
+ discovery.
+
``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 +418,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 +482,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}"
@@ -515,6 +523,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 0f79c9a..6b3bf34 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 331623f..4d3bfe2 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -80,19 +80,34 @@ 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"
+ )
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 967ad7b..c115f00 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 cbd748b..c72bf6d 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 0a9c487..8a0c972 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 0000000..ff35897
--- /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 0000000..8ebe19a
--- /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/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 5c8f152..9808861 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)
@@ -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 1b0815e..4ee7643 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 9a18184..8dc44a0 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,7 @@ set(SRCS
cmProcessOutput.h
cmProcessTools.cxx
cmProcessTools.h
+ cmProperty.cxx
cmProperty.h
cmPropertyDefinition.cxx
cmPropertyDefinition.h
@@ -834,7 +801,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 +961,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 3ed80c3..8626aa5 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 2)
+set(CMake_VERSION_PATCH 20210920)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx
index 87ebbfe..c7ab994 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
+cmProp 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 42deda4..cf243dc 100644
--- a/Source/CPack/IFW/cmCPackIFWCommon.h
+++ b/Source/CPack/IFW/cmCPackIFWCommon.h
@@ -7,6 +7,8 @@
#include <map>
#include <string>
+#include "cmProperty.h"
+
class cmCPackIFWGenerator;
class cmXMLWriter;
@@ -26,7 +28,7 @@ public:
public:
// Internal implementation
- const char* GetOption(const std::string& op) const;
+ cmProp 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 2806c61..0e2aec0 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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);
+ cmProp 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)) {
+ cmProp 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 (cmProp 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 (cmProp 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 (cmProp dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) {
cmExpandList(dirs, this->RepoDirsVector);
}
@@ -330,23 +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 (cmProp 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 (cmProp 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 (cmProp ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) {
this->OnlineOnly = cmIsOn(ifwDownloadAll);
- } else if (const char* cpackDownloadAll =
- this->GetOption("CPACK_DOWNLOAD_ALL")) {
+ } else if (cmProp cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) {
this->OnlineOnly = cmIsOn(cpackDownloadAll);
} else {
this->OnlineOnly = false;
@@ -374,9 +373,8 @@ int cmCPackIFWGenerator::InitializeInternal()
}
// Output extension
- if (const char* optOutExt =
- this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) {
- this->OutputExtension = optOutExt;
+ if (cmProp optOutExt = this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) {
+ this->OutputExtension = *optOutExt;
} else if (sysName == "Darwin") {
this->OutputExtension = ".dmg";
} else {
@@ -508,21 +506,20 @@ std::string cmCPackIFWGenerator::GetRootPackageName()
{
// Default value
std::string name = "root";
- if (const char* optIFW_PACKAGE_GROUP =
+ if (cmProp 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 (cmProp 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 (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) {
// Configure from package name
- name = optPACKAGE_NAME;
+ name = *optPACKAGE_NAME;
}
return name;
}
@@ -537,10 +534,10 @@ std::string cmCPackIFWGenerator::GetGroupPackageName(
if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) {
return package->Name;
}
- const char* option =
+ cmProp 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 +560,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;
+ cmProp 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 bf8b457..23b73ff 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -12,6 +12,7 @@
#include "cmCPackIFWRepository.h"
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
@@ -33,61 +34,59 @@ void cmCPackIFWInstaller::printSkippedOptionWarning(
void cmCPackIFWInstaller::ConfigureFromOptions()
{
// Name;
- if (const char* 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;
+ if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
+ this->Name = *optIFW_PACKAGE_NAME;
+ } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) {
+ this->Name = *optPACKAGE_NAME;
} else {
this->Name = "Your package";
}
// Title;
- if (const char* optIFW_PACKAGE_TITLE =
+ if (cmProp 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 (cmProp 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 (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) {
+ this->Version = *option;
} else {
this->Version = "1.0.0";
}
// Publisher
- if (const char* optIFW_PACKAGE_PUBLISHER =
+ if (cmProp 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 (cmProp 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 (cmProp option = this->GetOption("CPACK_IFW_PRODUCT_URL")) {
+ this->ProductUrl = *option;
}
// ApplicationIcon
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) {
+ if (cmProp 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 (cmProp 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 +102,45 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// Logo
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
+ if (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 +153,28 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// StyleSheet
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) {
+ if (cmProp 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 (cmProp option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) {
- this->WizardDefaultWidth = option;
+ this->WizardDefaultWidth = *option;
}
// WizardDefaultHeight
- if (const char* option =
+ if (cmProp option =
this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) {
- this->WizardDefaultHeight = option;
+ this->WizardDefaultHeight = *option;
}
// WizardShowPageList
- if (const char* option =
+ if (cmProp 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 +203,23 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// TitleColor
- if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
- this->TitleColor = option;
+ if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) {
+ this->TitleColor = *option;
}
// Start menu
- if (const char* optIFW_START_MENU_DIR =
+ if (cmProp 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 (cmProp 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 (cmProp optPACKAGE_INSTALL_DIRECTORY =
this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
this->TargetDir =
cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY);
@@ -229,21 +228,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 (cmProp option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
+ this->AdminTargetDir = *option;
}
// Maintenance tool
- if (const char* optIFW_MAINTENANCE_TOOL =
+ if (cmProp 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 (cmProp 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 +263,13 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
// Control script
- if (const char* optIFW_CONTROL_SCRIPT =
+ if (cmProp 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 (cmProp optIFW_PACKAGE_RESOURCES =
this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
this->Resources.clear();
cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources);
@@ -541,7 +539,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 (cmProp 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 1429c46..c1e11d2 100644
--- a/Source/CPack/IFW/cmCPackIFWPackage.cxx
+++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx
@@ -15,6 +15,7 @@
#include "cmCPackIFWInstaller.h"
#include "cmCPackLog.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
@@ -124,10 +125,10 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component)
if (!component) {
return "";
}
- const char* option =
+ cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = *optVERSION;
+ } else if (cmProp 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 (cmProp option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = *option;
}
// User interfaces
- if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ if (cmProp 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 (cmProp 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 (cmProp 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 (cmProp optVERSION = this->GetOption(prefix + "VERSION")) {
+ this->Version = *optVERSION;
+ } else if (cmProp 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 (cmProp option = this->GetOption(prefix + "SCRIPT")) {
+ this->Script = *option;
}
// User interfaces
- if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) {
+ if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) {
this->UserInterfaces.clear();
cmExpandList(option, this->UserInterfaces);
}
// Licenses
- if (const char* option = this->GetOption(prefix + "LICENSES")) {
+ if (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp value = this->GetOption(option)) {
cmExpandList(value, deps);
}
option = prefix + "DEPENDENCIES";
- if (const char* value = this->GetOption(option)) {
+ if (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 7ec2256..cc64e93 100644
--- a/Source/CPack/IFW/cmCPackIFWRepository.cxx
+++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx
@@ -6,6 +6,7 @@
#include "cmCPackIFWGenerator.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmSystemTools.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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp 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 (cmProp displayName = this->GetOption(prefix + "DISPLAY_NAME")) {
+ this->DisplayName = *displayName;
} else {
this->DisplayName.clear();
}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 8b3644f..e127c44 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUuid.h"
@@ -125,7 +126,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
command << " -ext " << QuotePath(ext);
}
- const char* const cultures = GetOption("CPACK_WIX_CULTURES");
+ cmProp 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) {
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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());
+ cmProp 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 (cmProp title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) {
+ featureTitle = *title;
}
featureDefinitions.AddAttribute("Title", featureTitle);
- if (const char* desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) {
+ if (cmProp 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");
+ cmProp 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 =
+ cmProp 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");
+ cmProp 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 (cmProp 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");
+ cmProp 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");
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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());
+ cmProp 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());
+ cmProp 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());
+ cmProp 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());
+ cmProp variableContent = GetOption(variableName);
if (!variableContent)
return;
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index d9234e6..4f90ba2 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>
@@ -13,6 +12,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
@@ -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) {
+ cmProp 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 4d5f43f..d93ddb8 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -6,6 +6,7 @@
#include <vector>
#include "cmCPackLog.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -15,8 +16,8 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() = default;
int cmCPackBundleGenerator::InitializeInternal()
{
- const char* name = this->GetOption("CPACK_BUNDLE_NAME");
- if (nullptr == name) {
+ cmProp 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()) {
+ cmProp 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()) {
+ cmProp 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()) {
+ cmProp 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")
- : "";
+ cmProp 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,10 @@ 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")
- : "";
+ cmProp 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 +185,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")
- : "";
+ cmProp 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 b5abd5a..1de5e1c 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -8,6 +8,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -59,14 +60,15 @@ int cmCPackCygwinBinaryGenerator::PackageFiles()
const char* cmCPackCygwinBinaryGenerator::GetOutputExtension()
{
this->OutputExtension = "-";
- const char* patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
+ cmProp 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 64a88eb..684a988 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -8,6 +8,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -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");
+ cmProp 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");
+ cmProp 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 006d66d..91b6c12 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"
@@ -19,6 +20,7 @@
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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,
+ cmProp debianCompressionType, cmProp numThreads,
+ cmProp 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,
+ cmProp 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,27 +64,28 @@ private:
const std::string PostInst;
const bool GenPostRm;
const std::string PostRm;
- const char* ControlExtra;
+ cmProp ControlExtra;
const bool PermissionStrictPolicy;
const std::vector<std::string> PackageFiles;
cmArchiveWrite::Compress TarCompressionType;
};
-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,
- 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 permissionStrictPolicy, std::vector<std::string> packageFiles)
+DebGenerator::DebGenerator(cmCPackLog* logger, std::string outputName,
+ std::string workDir, std::string topLevelDir,
+ std::string temporaryDir, cmProp debCompressionType,
+ cmProp numThreads, cmProp debianArchiveType,
+ std::map<std::string, std::string> controlValues,
+ bool genShLibs, std::string shLibsFilename,
+ bool genPostInst, std::string postInst,
+ bool genPostRm, std::string postRm,
+ cmProp 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 +97,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 +126,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 +193,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 +261,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 +326,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 +357,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 +371,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 +387,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 +403,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 +443,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 +472,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 +489,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 +538,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 +613,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 +627,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 +637,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 +679,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);
+ cmProp 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 +720,75 @@ 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 =
+ cmProp 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");
+ cmProp 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 =
+ cmProp 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 =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS");
+ cmProp 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 =
- this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE");
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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 =
+ cmProp 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");
+ cmProp 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 ee8f39a..61a6616 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 b71c969..36ab414 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -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")
- : "";
+ cmProp 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")
- : "";
+ cmProp 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")
- : "";
+ cmProp 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")
- : "";
+ cmProp 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")
- : "";
+ cmProp 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);
+ cmProp _groupName = this->GetOption(groupVar);
if (_groupName) {
std::string groupName = _groupName;
diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx
index e3521a0..9cdaafe 100644
--- a/Source/CPack/cmCPackExternalGenerator.cxx
+++ b/Source/CPack/cmCPackExternalGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -60,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles()
return 0;
}
- const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT");
+ cmProp 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);
+ cmProp 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");
+ cmProp packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME");
if (packageName) {
- root["packageName"] = packageName;
+ root["packageName"] = *packageName;
}
- const char* packageVersion =
- this->Parent->GetOption("CPACK_PACKAGE_VERSION");
+ cmProp packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION");
if (packageVersion) {
- root["packageVersion"] = packageVersion;
+ root["packageVersion"] = *packageVersion;
}
- const char* packageDescriptionFile =
+ cmProp packageDescriptionFile =
this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE");
if (packageDescriptionFile) {
- root["packageDescriptionFile"] = packageDescriptionFile;
+ root["packageDescriptionFile"] = *packageDescriptionFile;
}
- const char* packageDescriptionSummary =
+ cmProp 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");
+ cmProp buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG");
if (buildConfigCstr) {
- root["buildConfig"] = buildConfigCstr;
+ root["buildConfig"] = *buildConfigCstr;
}
- const char* defaultDirectoryPermissions =
+ cmProp 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 b673006..39ec3c8 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);
+ cmProp 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 00e274d..43efcf4 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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());
+ cmProp 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");
+ cmProp 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 =
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS");
{
- const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT");
+ cmProp 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");
+ cmProp cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
+ cmProp 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);
+ cmProp 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);
+ cmProp 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 =
+ cmProp 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);
@@ -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);
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, cmProp 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, cmProp 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");
+ cmProp 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 =
+ cmProp tempPackageFileName =
this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME");
- const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
+ cmProp 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");
+ cmProp 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 : "");
+ cmProp 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 = cmProp(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");
+ cmProp config = this->GetOption("CPACK_PROJECT_CONFIG_FILE");
if (config) {
mf->ReadListFile(config);
}
@@ -1250,15 +1259,14 @@ bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const
return false;
}
-const char* cmCPackGenerator::GetOption(const std::string& op) const
+cmProp cmCPackGenerator::GetOption(const std::string& op) const
{
cmProp 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);
+ cmProp 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);
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE");
if (cmNonempty(archiveFile)) {
- component->ArchiveFile = archiveFile;
+ component->ArchiveFile = *archiveFile;
}
- const char* plist = this->GetOption(macroPrefix + "_PLIST");
+ cmProp plist = this->GetOption(macroPrefix + "_PLIST");
if (cmNonempty(plist)) {
- component->Plist = plist;
+ component->Plist = *plist;
}
- const char* groupName = this->GetOption(macroPrefix + "_GROUP");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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");
+ cmProp 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 2512d42..e63a830 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -12,6 +12,7 @@
#include "cm_sys_stat.h"
#include "cmCPackComponentGroup.h"
+#include "cmProperty.h"
#include "cmSystemTools.h"
class cmCPackLog;
@@ -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, cmProp(value));
+ }
+ void SetOption(const std::string& op, cmProp 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, cmProp(value));
+ }
+ void SetOptionIfNotSet(const std::string& op, cmProp value);
+ cmProp 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 6bd0d1b..f151ff1 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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");
+ cmProp 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 =
+ cmProp cpackPackageExecutables =
this->GetOption("CPACK_PACKAGE_EXECUTABLES");
- const char* cpackPackageDeskTopLinks =
+ cmProp cpackPackageDeskTopLinks =
this->GetOption("CPACK_CREATE_DESKTOP_LINKS");
- const char* cpackNsisExecutablesDirectory =
+ cmProp 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");
+ cmProp 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");
+ cmProp 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(
+ cmProp 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 98dc890..c268f27 100644
--- a/Source/CPack/cmCPackNuGetGenerator.cxx
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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");
+ cmProp 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 5de4a6f..8291752 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -10,6 +10,7 @@
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -22,7 +23,7 @@ int cmCPackOSXX11Generator::PackageFiles()
// TODO: Use toplevel ?
// It is used! Is this an obsolete comment?
- const char* cpackPackageExecutables =
+ cmProp 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");
+ cmProp 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 ac3d64d..171fbb2 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -7,6 +7,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -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);
+ cmProp 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"));
+ cmProp 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);
+ cmProp 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 f51ea42..2915616 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -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");
+ cmProp preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
+ cmProp postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
+ cmProp 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");
+ cmProp 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) {
+ cmProp 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) {
+ cmProp 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 a3e55de..614b538 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -10,6 +10,7 @@
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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 (cmProp n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) {
identityName = n;
}
std::string keychainPath;
- if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) {
+ if (cmProp 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);
+ cmProp preflight = this->GetComponentScript("PREFLIGHT", comp_name);
+ cmProp 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 (cmProp n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) {
identityName = n;
}
std::string keychainPath;
- if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
+ if (cmProp p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) {
keychainPath = p;
}
@@ -239,7 +240,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
return RunProductBuild(pkgCmd.str());
}
-const char* cmCPackProductBuildGenerator::GetComponentScript(
+cmProp 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 462e2fc..8f169b0 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.h
+++ b/Source/CPack/cmCPackProductBuildGenerator.h
@@ -8,6 +8,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackPKGGenerator.h"
+#include "cmProperty.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);
+ cmProp GetComponentScript(const char* script, const char* script_component);
};
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index c3f6d59..47db5bb 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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");
+ cmProp 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 ad0a3e2..4b34c08 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmArchiveWrite.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmProperty.h"
#include "cmSystemTools.h"
cmCPackSTGZGenerator::cmCPackSTGZGenerator()
@@ -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/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx
index 48cc0e4..dc7103a 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, cmProp 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, cmProp 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,
+ cmProp 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)
+cmProp 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 cmProp(remit->second);
}
std::vector<std::string> cmCTestGenericHandler::GetMultiOption(
diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h
index e846fd9..852d4ea 100644
--- a/Source/CTest/cmCTestGenericHandler.h
+++ b/Source/CTest/cmCTestGenericHandler.h
@@ -11,6 +11,7 @@
#include <stddef.h>
#include "cmCTest.h"
+#include "cmProperty.h"
#include "cmSystemTools.h"
class cmGeneratedFileStream;
@@ -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, cmProp(value));
+ }
+ void SetPersistentOption(const std::string& op, cmProp 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, cmProp(value));
+ }
+ void SetOption(const std::string& op, cmProp value);
+ cmProp GetOption(const std::string& op);
/**
* Multi-Options collect one or more values from flags; passing
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 125d003..6bb8e79 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 b200c43..a63a24d 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 86a8e00..d90c4a6 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 a892113..20f0ed3 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);
@@ -749,6 +788,127 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
}
}
+ 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) {
+ auto entry = env_application.find(name);
+ std::string output;
+ if (entry != env_application.end() && entry->second) {
+ output = *entry->second;
+ }
+ apply(output);
+ entry->second = 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 863ac1b..2082156 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/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 53e1b2f..a8c2403 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -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;
+ cmProp src_dir;
+ cmProp 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 = cmProp(args[cnt]);
cnt++;
} else if (!bld_dir) {
- bld_dir = &args[cnt];
+ bld_dir = cmProp(args[cnt]);
cnt++;
} else {
this->SetError("Too many arguments");
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index bdba0e5..6824752 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -36,8 +36,8 @@ std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
- const std::string* submitURL = !this->SubmitURL.empty()
- ? &this->SubmitURL
+ cmProp submitURL = !this->SubmitURL.empty()
+ ? cmProp(this->SubmitURL)
: this->Makefile->GetDefinition("CTEST_SUBMIT_URL");
if (submitURL) {
@@ -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 5b54573..9322bd5 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -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;
@@ -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");
+ cmProp cdashUploadFile = this->GetOption("CDashUploadFile");
+ cmProp 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 67f4986..80b8d4f 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -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);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 730ec0f..c41b661 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -32,6 +32,7 @@
#include "cmCTest.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCTestResourceGroupsLexerHelper.h"
+#include "cmCTestTestMeasurementXMLParser.h"
#include "cmDuration.h"
#include "cmExecutionStatus.h"
#include "cmGeneratedFileStream.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 (cmProp 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");
+ cmProp 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");
@@ -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(cmProp 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 bd51738..585a336 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 "cmProperty.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(cmProp);
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 0000000..636be24
--- /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 0000000..b2c3eb3
--- /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 797cb01..6655bf7 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 57cc024..7c7c380 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -17,6 +17,7 @@
#include "cmCTestSVN.h"
#include "cmCTestVC.h"
#include "cmGeneratedFileStream.h"
+#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
@@ -108,7 +109,7 @@ int cmCTestUpdateHandler::ProcessHandler()
static_cast<void>(fixLocale);
// Get source dir
- const char* sourceDirectory = this->GetOption("SourceDirectory");
+ cmProp 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 25bbb2f..70269ea 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/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx
index 3f3ddde..50e9752 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 a3e1c24..8ef1903 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/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index e6faef4..41e8a55 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -128,11 +128,11 @@ void QCMake::setBinaryDirectory(const QString& _dir)
}
cmProp gen = state->GetCacheEntryValue("CMAKE_GENERATOR");
if (gen) {
- const std::string* extraGen =
+ cmProp 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()));
}
@@ -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/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx
index 205c1c7..a0d5732 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 c192e2a..a1830f9 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 54b2998..9e0d80c 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 99707a3..a69c00d 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/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 0550568..74071ff 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -2,214 +2,510 @@
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 "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());
- // Otherwise, find a VS 16 instance ourselves.
- cmVSSetupAPIHelper vsSetupAPIHelper(16);
- if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
- cmSystemTools::ConvertToUnixSlashes(value);
+ // 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;
+ }
+
+ 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{};
+}
+
+#ifdef HAVE_VS_SETUP_HELPER
+cm::optional<std::string> GetValue(cmExecutionStatus& status,
+ std::string const& key)
+{
+ 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;
+ }
+ }
+
+ return {};
}
+#endif
-std::string ValueToString(const char* value)
+cm::optional<std::string> GetValueChained()
{
- std::string safe_string = value ? value : "";
- return safe_string;
+ return {};
}
-std::string ValueToString(std::string const& value)
+template <typename GetterFn, typename... Next>
+cm::optional<std::string> GetValueChained(GetterFn current, Next... chain)
{
- return value;
+ 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/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx
index 1f99043..b2830e2 100644
--- a/Source/cmCMakePolicyCommand.cxx
+++ b/Source/cmCMakePolicyCommand.cxx
@@ -6,6 +6,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index ace7382..e922ee5 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -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,
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 1a950df..17369c8 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -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);
@@ -500,7 +500,7 @@ cmProp cmCacheManager::GetInitializedCacheValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
if (entry->Initialized) {
- return &entry->GetValue();
+ return cmProp(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, cmProp 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(cmProp value)
{
if (value) {
- this->Value = value;
+ this->Value = *value;
this->Initialized = true;
} else {
this->Value.clear();
@@ -568,10 +568,10 @@ std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
cmProp cmCacheManager::CacheEntry::GetProperty(const std::string& prop) const
{
if (prop == "TYPE") {
- return &cmState::CacheEntryTypeToString(this->Type);
+ return cmProp(cmState::CacheEntryTypeToString(this->Type));
}
if (prop == "VALUE") {
- return &this->Value;
+ return cmProp(this->Value);
}
return this->Properties.GetPropertyValue(prop);
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 7a9a7dc..eca7150 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -31,7 +31,7 @@ class cmCacheManager
public:
const std::string& GetValue() const { return this->Value; }
- void SetValue(const char*);
+ void SetValue(cmProp);
cmStateEnums::CacheEntryType GetType() const { return this->Type; }
void SetType(cmStateEnums::CacheEntryType ty) { this->Type = ty; }
@@ -75,7 +75,7 @@ public:
cmProp GetCacheEntryValue(const std::string& key) const
{
if (const auto* entry = this->GetCacheEntry(key)) {
- return &entry->GetValue();
+ return cmProp(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(cmProp(value));
}
}
@@ -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 ? cmProp(std::string(value)) : cmProp(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key, cmProp(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmProp value,
const char* helpString,
cmStateEnums::CacheEntryType type);
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index deddba8..415f0c0 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -113,7 +113,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 7c2e20c..59e4141 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -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)
+cmProp 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(
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index a156a41..463a445 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "cmProperty.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);
+ cmProp 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 0b27e34..15a12ba 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -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 d15da0c..eda0722 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -278,13 +278,11 @@ 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.
@@ -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;
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 7fe30b3..c3ae345 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -14,6 +14,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmListFileCache.h"
+#include "cmProperty.h"
class cmGeneratorTarget;
class cmGlobalGenerator;
@@ -137,7 +138,7 @@ private:
SharedDepModeLink // List file on link line
};
- const char* LoaderFlag;
+ cmProp LoaderFlag;
std::string LibLinkFlag;
std::string LibLinkFileFlag;
std::string ObjLinkFileFlag;
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 76712f4..5d3e04f 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -323,7 +323,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 &&
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index f99592c..1d7696d 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -2,16 +2,21 @@
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"
@@ -20,40 +25,184 @@
#include "cmSystemTools.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
@@ -147,11 +300,13 @@ cmProp cmConditionEvaluator::GetDefinitionIfUnquoted(
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);
@@ -168,15 +323,16 @@ cmProp cmConditionEvaluator::GetVariableOrString(
cmProp def = this->GetDefinitionIfUnquoted(argument);
if (!def) {
- def = &argument.GetValue();
+ def = cmProp(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);
@@ -242,7 +393,7 @@ bool cmConditionEvaluator::GetBooleanValue(
//=========================================================================
// 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.
@@ -257,8 +408,8 @@ bool cmConditionEvaluator::GetBooleanValueOld(
}
// Old GetVariableOrNumber behavior.
cmProp def = this->GetDefinitionIfUnquoted(arg);
- if (!def && atoi(arg.GetValue().c_str())) {
- def = &arg.GetValue();
+ if (!def && std::atoi(arg.GetValue().c_str())) {
+ def = cmProp(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:
@@ -304,56 +455,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 +488,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 +525,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 +632,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)) {
+ cmProp def = this->GetDefinitionIfUnquoted(*args.current);
+
+ std::string def_buf;
+ if (!def) {
+ def = cmProp(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 = cmProp(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))) {
+
+ cmProp ldef = this->GetVariableOrString(*args.current);
+ cmProp 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 cmProp lhs = this->GetVariableOrString(*args.current);
+ const cmProp 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) {
+
+ cmProp lhs = this->GetVariableOrString(*args.current);
+ cmProp 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 +777,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 +794,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 cf00ede..00d896b 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"
+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(
const cmExpandedCommandArgument& argument) const;
cmProp 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 aeca6b4..6a419f6 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 bf18143..0c85d28 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -606,7 +606,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
std::string langFlags = "CMAKE_" + li + "_FLAGS";
cmProp 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",
@@ -644,9 +644,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
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());
+ fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(),
+ cmOutputConverter::EscapeForCMake(*flagsCfg).c_str());
}
} break;
}
@@ -679,8 +678,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
cmProp 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;
}
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 233790e..fa001d2 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
@@ -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 fb716f8..9c1e337 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -11,3 +11,4 @@
std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr);
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/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 4a4f87d..9e2d7b9 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)
+cmProp 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 ? cmProp(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 b650aa8..ee1db7a 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -12,6 +12,7 @@
#include <cm/string_view>
#include "cmLinkedTree.h"
+#include "cmProperty.h"
#include "cmString.hxx"
/** \class cmDefinitions
@@ -28,8 +29,7 @@ class cmDefinitions
public:
// -- Static member functions
- static const std::string* Get(const std::string& key, StackIter begin,
- StackIter end);
+ static cmProp Get(const std::string& key, StackIter begin, StackIter end);
static void Raise(const std::string& key, StackIter begin, StackIter end);
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index bca26b9..6024cf6 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -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;
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index 0d407bc..a74db91 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 9a474e3..1678ce8 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 f88ebe9..ce8bd7f 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 1a31ae4..6e3f918 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
@@ -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 264494d..244f526 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/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index dd611de..8b06a15 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -27,7 +27,6 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
-#include "cmTargetExport.h"
static std::string cmExportFileGeneratorEscape(std::string const& str)
{
@@ -123,7 +122,7 @@ 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);
@@ -134,7 +133,7 @@ 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)
{
@@ -168,7 +167,7 @@ void cmExportFileGenerator::GenerateRequiredCMakeVersion(
}
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
- cmGeneratorTarget* target,
+ cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
@@ -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,10 +334,10 @@ 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";
@@ -366,10 +365,10 @@ 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";
@@ -378,7 +377,8 @@ void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
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,10 +424,10 @@ 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";
@@ -455,10 +455,10 @@ 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";
@@ -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)
{
@@ -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.
@@ -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,7 +1211,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
}
bool cmExportFileGenerator::PopulateExportProperties(
- cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ cmGeneratorTarget const* gte, ImportPropertyMap& properties,
std::string& errorMessage)
{
const auto& targetProperties = gte->Target->GetProperties();
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 45eaed0..24e048b 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 3c69c50..46d2d31 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -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 2d8de9d..5cec2e0 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/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index cac60e1..f89d0ad 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -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 6bf5781..127b8df 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/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index a2b5460..adeba74 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -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 (cmProp def = s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
minimumCMakeVersion = Json::objectValue;
minimumCMakeVersion["string"] = *def;
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 0ad59c7..1223d2a 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"
@@ -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)
{
@@ -1242,8 +1210,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 +1233,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,
@@ -1858,7 +1821,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmProp(*i);
} else {
status.SetError("DOWNLOAD missing file value for TLS_CAINFO.");
return false;
@@ -1984,9 +1947,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);
@@ -2244,7 +2205,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
} else if (*i == "TLS_CAINFO") {
++i;
if (i != args.end()) {
- cainfo = &(*i);
+ cainfo = cmProp(*i);
} else {
status.SetError("UPLOAD missing file value for TLS_CAINFO.");
return false;
@@ -2300,9 +2261,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);
diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h
index 217d58d..ee9872d 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 c89be96..0d8ba2d 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"
@@ -18,6 +23,7 @@ using namespace cmFSPermissions;
cmFileInstaller::cmFileInstaller(cmExecutionStatus& status)
: cmFileCopier(status, "INSTALL")
, InstallType(cmInstallType_FILES)
+ , InstallMode(cmInstallMode::COPY)
, Optional(false)
, MessageAlways(false)
, MessageLazy(false)
@@ -82,6 +88,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 +234,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 3a905d3..3f6bd45 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 1038ac2..37f9572 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -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/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 0cbe637..ef960d1 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -259,6 +259,34 @@ struct cmFindLibraryHelper
};
};
+namespace {
+
+std::string const& get_prefixes(cmMakefile* mf)
+{
+#ifdef _WIN32
+ static std::string defaultPrefix = ";lib";
+#else
+ static std::string defaultPrefix = "lib";
+#endif
+ cmProp 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
+ cmProp 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 fba736e..a0de74c 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -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;
}
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 4845a6d..b44f797 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -27,6 +27,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h
index 1b14d17..70fe537 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 054a2a9..efcc5bb 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 217ebe5..4e06a07 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -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";
}
@@ -1777,7 +1775,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
testedFeatures[lang].push_back(p);
if (availableFeatures.find(lang) == availableFeatures.end()) {
- const char* featuresKnown =
+ cmProp featuresKnown =
standardResolver.CompileFeaturesAvailable(lang, &error);
if (!featuresKnown) {
reportError(context, content->GetOriginalExpression(), error);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f1ef130..4bad7ab 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -62,7 +62,7 @@ cmProp 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
+cmProp 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 cmProp(value);
}
cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
@@ -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(
@@ -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 = cmProp(frameworkPostfix);
}
}
return postfix ? *postfix : std::string();
@@ -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(
@@ -966,7 +953,7 @@ cmProp cmGeneratorTarget::GetLanguageStandard(std::string const& lang,
this->GetLanguageStandardProperty(lang, config);
if (languageStandard) {
- return &(languageStandard->Value);
+ return cmProp(languageStandard->Value);
}
return nullptr;
@@ -1681,9 +1668,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() == '>') {
@@ -2142,7 +2129,6 @@ 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);
@@ -2155,21 +2141,17 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
// CMAKE_EXECUTABLE_FORMAT.
if (cmProp 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;
}
@@ -4105,7 +4087,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 +4105,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()) {
@@ -4466,6 +4448,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"
@@ -4966,11 +4955,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 +4992,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;
+ cmProp version;
#else
// Check for executable version properties.
- const char* version = cmToCStr(this->GetProperty("VERSION"));
+ cmProp version = this->GetProperty("VERSION");
if (this->GetType() != cmStateEnums::EXECUTABLE ||
this->Makefile->IsOn("XCODE")) {
version = nullptr;
@@ -5030,7 +5019,7 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
#endif
if (version) {
targetNames.Real += "-";
- targetNames.Real += version;
+ targetNames.Real += *version;
}
#if defined(__CYGWIN__)
targetNames.Real += suffix;
@@ -5119,13 +5108,13 @@ void cmGeneratorTarget::GetFullNameInternal(
if (this->IsFrameworkOnApple()) {
fw_prefix =
cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmProp(fw_prefix);
targetSuffix = nullptr;
}
if (this->IsCFBundleOnApple()) {
fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
- targetPrefix = &fw_prefix;
+ targetPrefix = cmProp(fw_prefix);
targetSuffix = nullptr;
}
@@ -5141,7 +5130,7 @@ void cmGeneratorTarget::GetFullNameInternal(
// EXECUTABLE_SUFFIX attribute.
if (this->IsFrameworkOnApple() &&
this->GetGlobalGenerator()->GetName() == "Xcode") {
- targetSuffix = &configPostfix;
+ targetSuffix = cmProp(configPostfix);
} else {
outBase += configPostfix;
}
@@ -5672,6 +5661,11 @@ std::string valueAsString<std::string>(std::string value)
return value;
}
template <>
+std::string valueAsString<cmProp>(cmProp value)
+{
+ return value ? value : std::string("(unset)");
+}
+template <>
std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
{
return "(unset)";
@@ -5747,7 +5741,7 @@ std::string getTypedProperty<std::string>(
cmProp value = tgt->GetProperty(prop);
if (genexInterpreter == nullptr) {
- return valueAsString(cmToCStr(value));
+ return valueAsString(value);
}
return genexInterpreter->Evaluate(value ? *value : "", prop);
@@ -6175,6 +6169,14 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory(
return this->FortranModuleDirectory;
}
+bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const
+{
+ if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) {
+ return cmIsOn(*prop);
+ }
+ return false;
+}
+
std::string cmGeneratorTarget::CreateFortranModuleDirectory(
std::string const& working_dir) const
{
@@ -6281,17 +6283,14 @@ std::string cmGeneratorTarget::GetFrameworkVersion() const
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, cmProp 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 +6357,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 +6388,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();
}
@@ -6903,23 +6905,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 +6931,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;
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)";
}
@@ -7085,10 +7077,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) {
@@ -7381,9 +7370,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);
@@ -7611,23 +7600,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;
@@ -7685,7 +7672,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 +7687,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 +7715,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 +7741,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);
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 6d2aa85..0076085 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -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;
+ cmProp GetSourcesProperty() const;
void AddISPCGeneratedHeader(std::string const& header,
std::string const& config);
@@ -901,8 +903,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, cmProp version) const;
struct CompatibleInterfacesBase
{
@@ -1037,11 +1038,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;
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index 7fbd479..d98f95c 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -13,6 +13,8 @@
namespace {
void StoreResult(cmMakefile& makefile, std::string const& variable,
const char* prop);
+void StoreResult(cmMakefile& makefile, std::string const& variable,
+ cmProp 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,
+ cmProp prop)
+{
+ makefile.AddDefinition(variable, prop);
+}
}
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index cb657f9..4b380c0 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -268,6 +268,11 @@ bool StoreResult(OutType infoType, cmMakefile& makefile,
}
return true;
}
+bool StoreResult(OutType infoType, cmMakefile& makefile,
+ const std::string& variable, cmProp value)
+{
+ return StoreResult(infoType, makefile, variable, value.GetCStr());
+}
bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
OutType infoType, const std::string& variable,
@@ -280,9 +285,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 +333,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,
@@ -365,8 +369,7 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
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 +394,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 +431,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,
@@ -447,7 +449,7 @@ bool HandleCacheMode(cmExecutionStatus& status, const std::string& 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/cmGetTestPropertyCommand.cxx b/Source/cmGetTestPropertyCommand.cxx
index cf8c1d5..077353e 100644
--- a/Source/cmGetTestPropertyCommand.cxx
+++ b/Source/cmGetTestPropertyCommand.cxx
@@ -4,6 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmTest.h"
bool cmGetTestPropertyCommand(std::vector<std::string> const& args,
@@ -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;
+ cmProp 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 32238e4..12fd9c4 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -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
diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx
index 9e5bbca..24c8944 100644
--- a/Source/cmGlobalCommonGenerator.cxx
+++ b/Source/cmGlobalCommonGenerator.cxx
@@ -16,8 +16,8 @@
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
-
-class cmake;
+#include "cmSystemTools.h"
+#include "cmake.h"
cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
: cmGlobalGenerator(cm)
@@ -95,3 +95,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);
+ }
+ }
+ cmProp 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 2aa9d27..fed9ce8 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 9193778..fd1a197 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -242,7 +242,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
std::vector<std::string> cnameArgVec;
if (cname && !cname->empty()) {
cmExpandList(*cname, cnameArgVec);
- cname = &cnameArgVec.front();
+ cname = cmProp(cnameArgVec.front());
}
std::string changeVars;
@@ -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();
@@ -1167,10 +1179,10 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l,
}
}
-const char* cmGlobalGenerator::GetGlobalSetting(std::string const& name) const
+cmProp 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 +1195,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 +1263,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());
}
}
}
@@ -1708,10 +1718,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 +1733,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 =
@@ -1771,9 +1775,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));
}
}
@@ -2182,9 +2185,8 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen,
this->TryCompileOuterMakefile = mf;
cmProp 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());
@@ -2740,7 +2742,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);
}
@@ -2812,12 +2814,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 +2850,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
if (this->UseFolderProperty()) {
target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
}
-
- return target;
}
std::string cmGlobalGenerator::GenerateRuleFile(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 147146e..34646d9 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -23,6 +23,7 @@
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmExportSet.h"
+#include "cmProperty.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -308,7 +309,7 @@ public:
cmExportSetMap& GetExportSets() { return this->ExportSets; }
- const char* GetGlobalSetting(std::string const& name) const;
+ cmProp GetGlobalSetting(std::string const& name) const;
bool GlobalSettingIsOn(std::string const& name) const;
std::string GetSafeGlobalSetting(std::string const& name) const;
@@ -596,7 +597,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;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 7cf3e93..b81f82e 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -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\"");
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index f08b1da..5ca8d52 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -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(
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 971a462..6279d68 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -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 (";
@@ -721,21 +720,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 +752,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 +919,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);
@@ -1021,13 +1013,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
{
@@ -1849,7 +1834,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 +1928,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 bb4ce2b..ec73475 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;
@@ -489,7 +488,6 @@ protected:
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 9c3de1e..d9f94a1 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -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
{
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 7c950cc..94ee476 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 fdb7155..488ff2e 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\".";
}
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 0083c40..21ea7e6 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -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)
+ cmProp 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";
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 7d38199..30ebf08 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,
+ cmProp 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 0c85a044..2a142ae 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -107,14 +107,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 +296,25 @@ void cmGlobalVisualStudio7Generator::Generate()
this->CallVisualStudioMacro(MacroReload,
GetSLNFile(this->LocalGenerators[0].get()));
}
+
+ if (this->Version == VS10 && !this->CMakeInstance->GetIsInTryCompile()) {
+ std::string cmakeWarnVS10;
+ if (cmProp 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(
@@ -379,10 +391,9 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
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");
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 148762e..1e34792 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -6,6 +6,7 @@
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
+#include "cmProperty.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,
+ cmProp typeGuid,
const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0;
std::string ConvertToSolutionPath(const std::string& path);
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index d0ad53e..3ecf32e 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -467,9 +467,9 @@ 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);
}
return true;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 77403b0..4ccc955 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);
@@ -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);
}
}
@@ -3248,9 +3241,8 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
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;
}
@@ -3817,7 +3809,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 +3839,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 +3906,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);
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index 5b532ce..c8b4a39 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 aefd098..d48c823 100644
--- a/Source/cmIncludeGuardCommand.cxx
+++ b/Source/cmIncludeGuardCommand.cxx
@@ -4,6 +4,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
diff --git a/Source/cmIncludeRegularExpressionCommand.cxx b/Source/cmIncludeRegularExpressionCommand.cxx
index 655ebd6..cdcc7df 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 79109b5..687741b 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -36,6 +36,7 @@
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmRuntimeDependencyArchive.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -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]
diff --git a/Source/cmInstallMode.h b/Source/cmInstallMode.h
new file mode 100644
index 0000000..5343d34
--- /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/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 4f7c959..2e444f2 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/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3b282de..4c3e8ec 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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));
}
}
}
@@ -426,27 +425,25 @@ void cmLocalGenerator::ProcessEvaluationFiles(
void cmLocalGenerator::GenerateInstallRules()
{
// Compute the install prefix.
- const char* prefix =
- cmToCStr(this->Makefile->GetDefinition("CMAKE_INSTALL_PREFIX"));
+ cmProp 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");
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 +452,13 @@ void cmLocalGenerator::GenerateInstallRules()
}
}
#else
- if (!prefix) {
+ if (!installPrefix) {
prefix = "/usr/local";
}
#endif
if (cmProp stagingPrefix =
this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX")) {
- prefix = stagingPrefix->c_str();
+ prefix = *stagingPrefix;
}
// Compute the set of configurations.
@@ -878,9 +875,12 @@ std::string cmLocalGenerator::GetIncludeFlags(
// Support special system include flag if it is available and the
// normal flag is repeated for each directory.
cmProp sysIncludeFlag = nullptr;
+ cmProp 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(
@@ -889,6 +889,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
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]) {
@@ -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.
@@ -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, cmProp 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;
});
}
@@ -1893,7 +1910,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
cmProp 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)) {
@@ -1944,10 +1961,10 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
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 (cmSystemTools::VersionCompare(
+ cmSystemTools::OP_GREATER_EQUAL,
+ this->Makefile->GetDefinition("CMAKE_Swift_COMPILER_VERSION"),
+ "4.2")) {
this->AppendFlags(flags, "-swift-version " + *v);
}
}
@@ -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,13 +2560,18 @@ 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");
+ cmProp pchExtension =
+ this->Makefile->GetDefinition("CMAKE_PCH_EXTENSION");
- if (pchExtension.empty()) {
+ if (pchExtension.IsEmpty()) {
continue;
}
@@ -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
@@ -2771,7 +2804,7 @@ 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);
}
}
@@ -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);
}
}
}
@@ -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
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 993280a..678ef8c 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -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
{
@@ -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);
+ cmProp sysroot);
void CopyPchCompilePdb(const std::string& config, cmGeneratorTarget* target,
const std::string& ReuseFrom,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 7f7b1e7..9f8e7ed 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -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();
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 151470b..7b5fed6 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -566,7 +566,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);
}
@@ -1779,7 +1779,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);
}
@@ -2142,7 +2142,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 002f484..acddfe1 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,7 +172,7 @@ 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")) {
+ if (this->GetGlobalGenerator()->IsVisualStudio()) {
cmProp extraPath = this->Makefile->GetDefinition("CMAKE_MSVCIDE_RUN_PATH");
if (extraPath) {
script += newline;
@@ -236,6 +237,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 91fb6b0..0e7f63f 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 c970abe..f9b2562 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -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;
@@ -954,8 +926,7 @@ void cmMakefile::Generate(cmLocalGenerator& lg)
this->DoGenerate(lg);
cmProp 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 "
@@ -1386,10 +1357,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));
}
}
@@ -1444,7 +1415,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 +1436,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));
+ 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());
@@ -1877,16 +1847,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);
}
}
@@ -1956,7 +1926,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();
}
@@ -2118,15 +2088,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,
@@ -2300,7 +2278,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:
@@ -2571,12 +2549,7 @@ 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,
@@ -2959,7 +2932,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew(
break;
case ENVIRONMENT:
if (cmSystemTools::GetEnv(lookup, svalue)) {
- value = &svalue;
+ value = cmProp(svalue);
}
break;
case CACHE:
@@ -3182,6 +3155,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 +3532,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,
@@ -3570,13 +3560,13 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// 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");
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
@@ -3966,6 +3956,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, cmProp value)
+{
+ this->StateSnapshot.GetDirectory().SetProperty(prop, value, this->Backtrace);
+}
void cmMakefile::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
@@ -3987,7 +3981,7 @@ cmProp cmMakefile::GetProperty(const std::string& prop) const
return pair.first;
});
output = cmJoin(keys, ";");
- return &output;
+ return cmProp(output);
}
return this->StateSnapshot.GetDirectory().GetProperty(prop);
@@ -4426,13 +4420,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));
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 77e9c74..bad9d91 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>
@@ -32,7 +33,6 @@
#include "cmSourceFileLocationKind.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
-#include "cmStringAlgorithms.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, cmProp 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");
}
/**
@@ -762,6 +772,11 @@ public:
//! Set/Get a property of this directory
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmProp value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmProp(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
cmProp GetProperty(const std::string& prop) 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 3a2744e..306b38f 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -397,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(
@@ -577,12 +576,18 @@ 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) {
+ cmProp 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;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d0e3837..64992f2 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -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);
}
@@ -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) {
+ cmProp 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/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a3e5553..70b6d27 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -293,8 +293,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
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);
}
}
@@ -1000,7 +999,25 @@ 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) {
+ cmProp 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=";
@@ -1398,6 +1415,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
@@ -1725,7 +1749,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable(
cmProp 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;
@@ -1815,7 +1839,7 @@ void cmMakefileTargetGenerator::WriteObjectsStrings(
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);
diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx
index 45043fa..5908f74 100644
--- a/Source/cmMarkAsAdvancedCommand.cxx
+++ b/Source/cmMarkAsAdvancedCommand.cxx
@@ -6,6 +6,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 5c21d1b..96e9142 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -581,17 +581,23 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd(
}
}
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) {
+ cmProp 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;
}
@@ -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);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 609848b..7cc1581 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -774,8 +774,11 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmProp 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, "\" ");
}
@@ -874,8 +877,26 @@ 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) {
+ cmProp 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=";
@@ -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);
}
}
@@ -1260,8 +1280,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
if (firstForConfig) {
cmProp 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);
}
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index bae67e0..014da4d 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -29,7 +29,7 @@ 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:
@@ -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/cmPolicies.cxx b/Source/cmPolicies.cxx
index 01e8c04..fc839c5 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -10,6 +10,7 @@
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmProperty.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f7c0d25..a98e6c6 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -379,7 +379,10 @@ 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)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx
new file mode 100644
index 0000000..d012630
--- /dev/null
+++ b/Source/cmProperty.cxx
@@ -0,0 +1,113 @@
+
+#include "cmProperty.h"
+
+#include <string>
+
+#include <cmext/string_view>
+
+#include "cmStringAlgorithms.h"
+
+std::string cmProp::Empty;
+
+bool cmProp::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 cmProp::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 cmProp::IsNOTFOUND(cm::string_view value) noexcept
+{
+ return (value == "NOTFOUND"_s) || cmHasSuffix(value, "-NOTFOUND"_s);
+}
+
+int cmProp::Compare(cmProp 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 cmProp::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, cmProp v)
+{
+ o << *v;
+ return o;
+}
diff --git a/Source/cmProperty.h b/Source/cmProperty.h
index 1e03c3f..4179187 100644
--- a/Source/cmProperty.h
+++ b/Source/cmProperty.h
@@ -4,8 +4,12 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
+#include <iosfwd>
#include <string>
+#include <cm/string_view>
+
class cmProperty
{
public:
@@ -23,14 +27,213 @@ public:
};
};
-using cmProp = const std::string*;
+class cmProp
+{
+public:
+ cmProp() noexcept = default;
+ cmProp(std::nullptr_t) noexcept {}
+ explicit cmProp(const std::string* value) noexcept
+ : Value(value)
+ {
+ }
+ explicit cmProp(const std::string& value) noexcept
+ : Value(&value)
+ {
+ }
+ cmProp(const cmProp& other) noexcept = default;
-inline const char* cmToCStr(cmProp p)
+ cmProp& operator=(const cmProp& other) noexcept = default;
+ cmProp& 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 ? &cmProp::Empty : this->Value;
+ }
+ const std::string& operator*() const noexcept
+ {
+ return this->Value == nullptr ? cmProp::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 &&
+ cmProp::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 ||
+ cmProp::IsOff(cm::string_view(*this->Value));
+ }
+ /** Return true if value is NOTFOUND or ends in -NOTFOUND. */
+ bool IsNOTFOUND() const noexcept
+ {
+ return this->Value != nullptr &&
+ cmProp::IsNOTFOUND(cm::string_view(*this->Value));
+ }
+ bool IsEmpty() const noexcept
+ {
+ return this->Value == nullptr || this->Value->empty();
+ }
+
+ 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(cmProp 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(); }
+
+private:
+ static std::string Empty;
+ const std::string* Value = nullptr;
+};
+
+std::ostream& operator<<(std::ostream& o, cmProp v);
+
+inline bool operator==(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmProp l, cmProp r) noexcept
{
- return p ? p->c_str() : nullptr;
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmProp l, cmProp r) noexcept
+{
+ return l.Compare(r) >= 0;
}
-inline const char* cmToCStrSafe(cmProp p)
+inline bool operator==(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) == 0;
+}
+inline bool operator!=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) != 0;
+}
+inline bool operator<(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) < 0;
+}
+inline bool operator<=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) <= 0;
+}
+inline bool operator>(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) > 0;
+}
+inline bool operator>=(cmProp l, cm::string_view r) noexcept
+{
+ return l.Compare(r) >= 0;
+}
+
+inline bool operator==(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) == 0;
+}
+inline bool operator!=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) != 0;
+}
+inline bool operator<(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) < 0;
+}
+inline bool operator<=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) <= 0;
+}
+inline bool operator>(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) > 0;
+}
+inline bool operator>=(cmProp l, std::nullptr_t) noexcept
+{
+ return l.Compare(cmProp{}) >= 0;
+}
+
+/**
+ * Temporary wrapper
+ */
+inline const char* cmToCStr(cmProp p)
{
- return p ? p->c_str() : "";
+ return p.GetCStr();
}
diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx
index 06e151a..8ad3c6f 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, cmProp 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)
@@ -46,7 +55,7 @@ cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const
{
auto it = this->Map_.find(name);
if (it != this->Map_.end()) {
- return &it->second;
+ return cmProp(it->second);
}
return nullptr;
}
diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h
index cda585a..b28d3c9 100644
--- a/Source/cmPropertyMap.h
+++ b/Source/cmPropertyMap.h
@@ -26,6 +26,11 @@ public:
//! Set the property value
void SetProperty(const std::string& name, const char* value);
+ void SetProperty(const std::string& name, cmProp value);
+ void SetProperty(const std::string& name, const std::string& value)
+ {
+ this->SetProperty(name, cmProp(value));
+ }
//! Append to the property value
void AppendProperty(const std::string& name, const std::string& value,
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index e9670f9..ca0b259 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/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 77fe87e..f3ad565 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -186,7 +186,7 @@ void cmQtAutoGenGlobalInitializer::GetOrCreateGlobalTarget(
cmProp folder =
makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
if (folder) {
- target->SetProperty("FOLDER", *folder);
+ target->SetProperty("FOLDER", folder);
}
}
}
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 4dd78e5..fe038c7 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"
@@ -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"));
diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx
index 52b1a44..c2fc45c 100644
--- a/Source/cmSeparateArgumentsCommand.cxx
+++ b/Source/cmSeparateArgumentsCommand.cxx
@@ -4,6 +4,7 @@
#include <algorithm>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmArgumentParser.h"
@@ -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/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx
index 07ad246..9adf537 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 c899053..59b4402 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -294,7 +294,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 +474,7 @@ bool HandleGlobalMode(cmExecutionStatus& status,
if (remove) {
cm->SetProperty(propertyName, nullptr);
} else {
- cm->SetProperty(propertyName, propertyValue.c_str());
+ cm->SetProperty(propertyName, propertyValue);
}
}
@@ -520,7 +520,7 @@ bool HandleDirectoryMode(cmExecutionStatus& status,
if (remove) {
mf->SetProperty(propertyName, nullptr);
} else {
- mf->SetProperty(propertyName, propertyValue.c_str());
+ mf->SetProperty(propertyName, propertyValue);
}
}
@@ -631,7 +631,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 +681,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);
}
}
diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx
index 237b67f..ab93ddb 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 c4bff76..a17c964 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/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 3f3c8d5..6caae3a 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -269,7 +269,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 +295,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, cmProp value)
+{
+ this->StoreProperty(prop, value);
+}
+
void cmSourceFile::AppendProperty(const std::string& prop,
const std::string& value, bool asString)
{
@@ -342,7 +352,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 cmProp(this->GetOrDetermineLanguage());
}
// Special handling for GENERATED property.
@@ -355,9 +365,9 @@ cmProp cmSourceFile::GetPropertyForUser(const std::string& prop)
(policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)
? CheckScope::GlobalAndLocal
: CheckScope::Global)) {
- return &propTRUE;
+ return cmProp(propTRUE);
}
- return &propFALSE;
+ return cmProp(propFALSE);
}
// Perform the normal property lookup.
@@ -371,7 +381,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
if (this->FullPath.empty()) {
return nullptr;
}
- return &this->FullPath;
+ return cmProp(this->FullPath);
}
// Check for the properties with backtraces.
@@ -382,7 +392,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->IncludeDirectories, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_OPTIONS) {
@@ -392,7 +402,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileOptions, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
@@ -402,7 +412,7 @@ cmProp cmSourceFile::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->CompileDefinitions, ";");
- return &output;
+ return cmProp(output);
}
cmProp retVal = this->Properties.GetPropertyValue(prop);
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 32ed687..78e0d27 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -42,6 +42,11 @@ public:
//! Set/Get a property of this source file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmProp value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmProp(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
@@ -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 37ed4c1..499317d 100644
--- a/Source/cmStandardLevelResolver.cxx
+++ b/Source/cmStandardLevelResolver.cxx
@@ -57,10 +57,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))
@@ -308,31 +308,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 +389,11 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable(
return false;
}
- const char* features = this->CompileFeaturesAvailable(lang, error);
+ if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
+ return true;
+ }
+
+ cmProp features = this->CompileFeaturesAvailable(lang, error);
if (!features) {
return false;
}
@@ -465,7 +471,7 @@ bool cmStandardLevelResolver::CompileFeatureKnown(
return false;
}
-const char* cmStandardLevelResolver::CompileFeaturesAvailable(
+cmProp cmStandardLevelResolver::CompileFeaturesAvailable(
const std::string& lang, std::string* error) const
{
if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) {
@@ -507,7 +513,7 @@ const char* cmStandardLevelResolver::CompileFeaturesAvailable(
}
return nullptr;
}
- return cmToCStr(featuresKnown);
+ return featuresKnown;
}
bool cmStandardLevelResolver::GetNewRequiredStandard(
diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h
index d84fbcb..c01a3b1 100644
--- a/Source/cmStandardLevelResolver.h
+++ b/Source/cmStandardLevelResolver.h
@@ -30,8 +30,8 @@ public:
const std::string& feature, std::string& lang,
std::string* error) const;
- const char* CompileFeaturesAvailable(const std::string& lang,
- std::string* error) const;
+ cmProp CompileFeaturesAvailable(const std::string& lang,
+ std::string* error) const;
bool GetNewRequiredStandard(const std::string& targetName,
const std::string& feature,
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index ce6eb31..16718e8 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>();
@@ -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, cmProp 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;
@@ -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, cmProp value)
+{
+ this->GlobalProperties.SetProperty(prop, value);
+}
void cmState::AppendGlobalProperty(const std::string& prop,
const std::string& value, bool asString)
@@ -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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 cmProp(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 9951b9a..390f6d6 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -35,12 +35,6 @@ class cmState
friend class cmStateSnapshot;
public:
- cmState();
- ~cmState();
-
- cmState(const cmState&) = delete;
- cmState& operator=(const cmState&) = delete;
-
enum Mode
{
Unknown,
@@ -51,6 +45,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);
@@ -141,9 +147,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,6 +178,7 @@ public:
std::vector<std::string> GetCommandNames() const;
void SetGlobalProperty(const std::string& prop, const char* value);
+ void SetGlobalProperty(const std::string& prop, cmProp value);
void AppendGlobalProperty(const std::string& prop, const std::string& value,
bool asString = false);
cmProp GetGlobalProperty(const std::string& prop);
@@ -207,13 +211,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 ? cmProp(std::string(value)) : cmProp(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, cmStateEnums::CacheEntryType type)
+ {
+ this->AddCacheEntry(key, cmProp(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmProp value,
const char* helpString,
cmStateEnums::CacheEntryType type);
@@ -248,7 +265,6 @@ private:
std::string SourceDirectory;
std::string BinaryDirectory;
- bool IsInTryCompile = false;
bool IsGeneratorMultiConfig = false;
bool WindowsShell = false;
bool WindowsVSIDE = false;
@@ -258,5 +274,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 c898dd4..8f83b02 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -19,6 +19,7 @@
#include "cmState.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
static std::string const kBINARY_DIR = "BINARY_DIR";
@@ -63,7 +64,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 +74,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 +136,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 +250,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 +286,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 +294,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 +302,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,35 +310,46 @@ 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, cmProp 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;
}
@@ -450,17 +370,17 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
if (prop == "PARENT_DIRECTORY") {
cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
if (parent.IsValid()) {
- return &parent.GetDirectory().GetCurrentSource();
+ return cmProp(parent.GetDirectory().GetCurrentSource());
}
- return &output;
+ return cmProp(output);
}
if (prop == kBINARY_DIR) {
output = this->GetCurrentBinary();
- return &output;
+ return cmProp(output);
}
if (prop == kSOURCE_DIR) {
output = this->GetCurrentSource();
- return &output;
+ return cmProp(output);
}
if (prop == kSUBDIRECTORIES) {
std::vector<std::string> child_dirs;
@@ -471,15 +391,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 cmProp(output);
}
if (prop == kBUILDSYSTEM_TARGETS) {
output = cmJoin(this->DirectoryState->NormalTargetNames, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "IMPORTED_TARGETS"_s) {
output = cmJoin(this->DirectoryState->ImportedTargetNames, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LISTFILE_STACK") {
@@ -491,38 +411,38 @@ cmProp cmStateDirectory::GetProperty(const std::string& prop, bool chain) const
}
std::reverse(listFiles.begin(), listFiles.end());
output = cmJoin(listFiles, ";");
- return &output;
+ return cmProp(output);
}
if (prop == "CACHE_VARIABLES") {
output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";");
- return &output;
+ return cmProp(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 cmProp(output);
}
if (prop == "INCLUDE_DIRECTORIES") {
output = cmJoin(this->GetIncludeDirectoriesEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "COMPILE_OPTIONS") {
output = cmJoin(this->GetCompileOptionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "COMPILE_DEFINITIONS") {
output = cmJoin(this->GetCompileDefinitionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LINK_OPTIONS") {
output = cmJoin(this->GetLinkOptionsEntries(), ";");
- return &output;
+ return cmProp(output);
}
if (prop == "LINK_DIRECTORIES") {
output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
- return &output;
+ return cmProp(output);
}
cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index b8abccb..fac5d58c 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -14,7 +14,6 @@
#include "cmProperty.h"
#include "cmStatePrivate.h"
#include "cmStateSnapshot.h"
-#include "cmStringAlgorithms.h"
class cmStateDirectory
{
@@ -28,51 +27,37 @@ 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, cmProp 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;
@@ -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 6f475f2..fd46eed 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 fbf47ef..bd7db85 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -19,6 +19,10 @@
#include "cmSystemTools.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
+cmProp 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 =
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 d06cba3..a5fe7e2 100644
--- a/Source/cmStateSnapshot.h
+++ b/Source/cmStateSnapshot.h
@@ -12,6 +12,7 @@
#include "cmLinkedTree.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmStateTypes.h"
class cmState;
@@ -23,7 +24,7 @@ public:
cmStateSnapshot(cmState* state = nullptr);
cmStateSnapshot(cmState* state, cmStateDetail::PositionType position);
- std::string const* GetDefinition(std::string const& name) const;
+ cmProp 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 5bb6e7b..acb5e5b 100644
--- a/Source/cmStringAlgorithms.cxx
+++ b/Source/cmStringAlgorithms.cxx
@@ -227,76 +227,6 @@ bool cmIsInternallyOn(cm::string_view val)
(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 6b458ec..33ab403 100644
--- a/Source/cmStringAlgorithms.h
+++ b/Source/cmStringAlgorithms.h
@@ -14,25 +14,12 @@
#include <cm/string_view>
+#include "cmProperty.h"
#include "cmRange.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(cmProp 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(cmProp 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(cmProp value)
+ : View_(*value)
+ {
+ }
cm::string_view View() const { return this->View_; }
@@ -226,21 +232,52 @@ inline bool cmIsInternallyOn(const char* val)
}
return cmIsInternallyOn(cm::string_view(val));
}
+inline bool cmIsInternallyOn(cmProp val)
+{
+ if (!val) {
+ return false;
+ }
+ return cmIsInternallyOn(*val);
+}
+
+/** Check for non-empty Property/Variable value. */
+inline bool cmNonempty(cm::string_view val)
+{
+ return !cmProp::IsEmpty(val);
+}
+inline bool cmNonempty(const char* val)
+{
+ return !cmProp::IsEmpty(val);
+}
+inline bool cmNonempty(cmProp val)
+{
+ return !val.IsEmpty();
+}
/** Return true if value is NOTFOUND or ends in -NOTFOUND. */
-bool cmIsNOTFOUND(cm::string_view val);
+inline bool cmIsNOTFOUND(cm::string_view val)
+{
+ return cmProp::IsNOTFOUND(val);
+}
+inline bool cmIsNOTFOUND(cmProp val)
+{
+ return val.IsNOTFOUND();
+}
/**
* 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(cm::string_view val)
+{
+ return cmProp::IsOn(val);
+}
inline bool cmIsOn(const char* val)
{
- return val && cmIsOn(cm::string_view(val));
+ return cmProp::IsOn(val);
}
-inline bool cmIsOn(std::string const* val)
+inline bool cmIsOn(cmProp val)
{
- return val && cmIsOn(*val);
+ return val.IsOn();
}
/**
@@ -250,14 +287,17 @@ inline bool cmIsOn(std::string const* val)
* 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(cm::string_view val)
+{
+ return cmProp::IsOff(val);
+}
inline bool cmIsOff(const char* val)
{
- return !val || cmIsOff(cm::string_view(val));
+ return cmProp::IsOff(val);
}
-inline bool cmIsOff(std::string const* val)
+inline bool cmIsOff(cmProp val)
{
- return !val || cmIsOff(*val);
+ return val.IsOff();
}
/** Returns true if string @a str starts with the character @a prefix. */
@@ -273,6 +313,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, cmProp 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 +343,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, cmProp 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/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 10d2e50..27cb90f 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -20,6 +20,7 @@
#include <cm3p/uv.h>
#include "cmDuration.h"
+#include "cmELF.h"
#include "cmMessageMetadata.h"
#include "cmProcessOutput.h"
#include "cmRange.h"
@@ -46,10 +47,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 +1592,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 +1635,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 +2452,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 +2495,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 +2526,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 +2540,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 +2554,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 +2690,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 +2745,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 +2763,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 +2843,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 +2920,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 +3030,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 +3044,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 +3096,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 +3172,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 +3200,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 44ccbf7..715724c 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 7622700..af64dce 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -83,15 +83,15 @@ cmProp 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() == '>') {
@@ -157,7 +157,7 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>(
}
static std::string srcs;
srcs = ss.str();
- return &srcs;
+ return cmProp(srcs);
}
class cmTargetInternals
@@ -187,24 +187,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;
@@ -266,7 +258,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// Replace everything after "CMAKE_"
defKey.replace(defKey.begin() + 6, defKey.end(), property);
if (cmProp value = mf->GetDefinition(defKey)) {
- this->SetProperty(property, *value);
+ this->SetProperty(property, value);
}
};
auto initPropValue = [this, mf, &defKey](const std::string& property,
@@ -274,7 +266,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
// Replace everything after "CMAKE_"
defKey.replace(defKey.begin() + 6, defKey.end(), property);
if (cmProp value = mf->GetDefinition(defKey)) {
- this->SetProperty(property, *value);
+ this->SetProperty(property, value);
} else if (default_value) {
this->SetProperty(property, default_value);
}
@@ -481,8 +473,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 +482,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) {
@@ -612,11 +596,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 +710,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 +734,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 +822,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 +845,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;
@@ -1075,122 +1051,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<cmProp>(cmProp 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 +1200,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 +1266,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 +1297,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));
+ 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 +1355,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 +1393,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 +1417,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, cmProp value)
+{
+ this->StoreProperty(prop, value);
+}
+
void cmTarget::AppendBuildInterfaceIncludes()
{
if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
@@ -1501,70 +1453,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,
@@ -1681,31 +1609,6 @@ cmProp cmTarget::GetComputedProperty(const std::string& prop,
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
static std::unordered_set<std::string> const specialProps{
propC_STANDARD,
propCXX_STANDARD,
@@ -1737,7 +1640,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
if (propertyIter == this->impl->LanguageStandardProperties.end()) {
return nullptr;
}
- return &(propertyIter->second.Value);
+ return cmProp(propertyIter->second.Value);
}
if (prop == propLINK_LIBRARIES) {
if (this->impl->LinkImplementationPropertyEntries.empty()) {
@@ -1746,11 +1649,11 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkImplementationPropertyEntries, ";");
- return &output;
+ return cmProp(output);
}
// the type property returns what type the target is
if (prop == propTYPE) {
- return &cmState::GetTargetTypeName(this->GetType());
+ return cmProp(cmState::GetTargetTypeName(this->GetType()));
}
if (prop == propINCLUDE_DIRECTORIES) {
if (this->impl->IncludeDirectoriesEntries.empty()) {
@@ -1759,7 +1662,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->IncludeDirectoriesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_FEATURES) {
if (this->impl->CompileFeaturesEntries.empty()) {
@@ -1768,7 +1671,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileFeaturesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_OPTIONS) {
if (this->impl->CompileOptionsEntries.empty()) {
@@ -1777,7 +1680,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileOptionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propCOMPILE_DEFINITIONS) {
if (this->impl->CompileDefinitionsEntries.empty()) {
@@ -1786,7 +1689,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->CompileDefinitionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propLINK_OPTIONS) {
if (this->impl->LinkOptionsEntries.empty()) {
@@ -1795,7 +1698,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkOptionsEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propLINK_DIRECTORIES) {
if (this->impl->LinkDirectoriesEntries.empty()) {
@@ -1805,7 +1708,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->LinkDirectoriesEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
if (this->impl->Utilities.empty()) {
@@ -1822,7 +1725,7 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
return item.Value.first;
});
output = cmJoin(utilities, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propPRECOMPILE_HEADERS) {
if (this->impl->PrecompileHeadersEntries.empty()) {
@@ -1831,26 +1734,27 @@ cmProp cmTarget::GetProperty(const std::string& prop) const
static std::string output;
output = cmJoin(this->impl->PrecompileHeadersEntries, ";");
- return &output;
+ return cmProp(output);
}
if (prop == propIMPORTED) {
- return this->IsImported() ? &propTRUE : &propFALSE;
+ return this->IsImported() ? cmProp(propTRUE) : cmProp(propFALSE);
}
if (prop == propIMPORTED_GLOBAL) {
- return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE;
+ return this->IsImportedGloballyVisible() ? cmProp(propTRUE)
+ : cmProp(propFALSE);
}
if (prop == propNAME) {
- return &this->GetName();
+ return cmProp(this->GetName());
}
if (prop == propBINARY_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentBinary();
+ return cmProp(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentBinary());
}
if (prop == propSOURCE_DIR) {
- return &this->impl->Makefile->GetStateSnapshot()
- .GetDirectory()
- .GetCurrentSource();
+ return cmProp(this->impl->Makefile->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentSource());
}
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 30d9f5d..eced1ae 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -170,9 +170,10 @@ public:
//! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmProp value);
void SetProperty(const std::string& prop, const std::string& value)
{
- this->SetProperty(prop, value.c_str());
+ this->SetProperty(prop, cmProp(value));
}
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
@@ -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 dee2c10..8ca3842 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 1e38d84..19fc931 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 3897499..f31501e 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 0c68d60..3ba27a8 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/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx
index df9416f..3ea2d71 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/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
index f2be318..a749b53 100644
--- a/Source/cmTargetPropertyComputer.h
+++ b/Source/cmTargetPropertyComputer.h
@@ -65,7 +65,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocationForBuild(tgt);
+ return cmProp(ComputeLocationForBuild(tgt));
}
// Support "LOCATION_<CONFIG>".
@@ -76,7 +76,7 @@ private:
return nullptr;
}
std::string configName = prop.substr(9);
- return &ComputeLocation(tgt, configName);
+ return cmProp(ComputeLocation(tgt, configName));
}
// Support "<CONFIG>_LOCATION".
@@ -89,7 +89,7 @@ private:
context)) {
return nullptr;
}
- return &ComputeLocation(tgt, configName);
+ return cmProp(ComputeLocation(tgt, configName));
}
}
}
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index a26bef3..9d25ce9 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -32,7 +32,7 @@ void cmTest::SetCommand(std::vector<std::string> const& command)
this->Command = command;
}
-const char* cmTest::GetProperty(const std::string& prop) const
+cmProp cmTest::GetProperty(const std::string& prop) const
{
cmProp retVal = this->Properties.GetPropertyValue(prop);
if (!retVal) {
@@ -40,12 +40,12 @@ const char* cmTest::GetProperty(const std::string& prop) const
this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST);
if (chain) {
if (cmProp p = this->Makefile->GetProperty(prop, chain)) {
- return p->c_str();
+ 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, cmProp 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 f33b7e2..a790501 100644
--- a/Source/cmTest.h
+++ b/Source/cmTest.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmListFileCache.h"
+#include "cmProperty.h"
#include "cmPropertyMap.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, cmProp value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmProp(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
- const char* GetProperty(const std::string& prop) const;
+ cmProp GetProperty(const std::string& prop) const;
bool GetPropertyAsBool(const std::string& prop) const;
cmPropertyMap& GetProperties() { return this->Properties; }
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 056696d..cfea4cf 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':
@@ -187,6 +192,24 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
}
}
+#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 loadStrftime = [] {
+ 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 strftime;
+ };
+ static T strftime = loadStrftime();
+#endif
+
char buffer[16];
size_t size =
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 97cb1bf..e7ef7ea 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -490,10 +490,7 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.Element("Platform", this->Platform);
cmProp projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = &this->Name;
- }
- e1.Element("ProjectName", *projLabel);
+ e1.Element("ProjectName", projLabel ? projLabel : this->Name);
{
cmProp targetFramework =
this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK");
@@ -511,15 +508,15 @@ void cmVisualStudio10TargetGenerator::Generate()
p = this->GeneratorTarget->GetProperty(
"DOTNET_TARGET_FRAMEWORK_VERSION");
}
- const char* targetFrameworkVersion = cmToCStr(p);
- if (!targetFrameworkVersion && this->ProjectType == csproj &&
+ std::string targetFrameworkVersion = p;
+ if (targetFrameworkVersion.empty() && this->ProjectType == csproj &&
this->GlobalGenerator->TargetsWindowsCE() &&
this->GlobalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS12) {
// VS12 .NETCF default to .NET framework 3.9
targetFrameworkVersion = "v3.9";
}
- if (targetFrameworkVersion) {
+ if (!targetFrameworkVersion.empty()) {
e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
}
}
@@ -1472,7 +1469,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 +1803,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 +1815,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 +1872,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 +1884,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;
@@ -2054,10 +2051,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
}
- if (cmProp p = sf->GetProperty("VS_SETTINGS")) {
- ParseSettingsProperty(*p, toolSettings);
- }
-
if (!toolSettings.empty()) {
toolHasSettings = true;
}
@@ -2067,27 +2060,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 +2197,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 (cmProp p = si.Source->GetProperty("VS_SETTINGS")) {
+ ParseSettingsProperty(*p, toolSettings);
+ }
+
const char* tool = nullptr;
switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
@@ -2251,10 +2233,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 +2346,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
if (!isCSharp && !exclude_configs.empty()) {
this->WriteExcludeFromBuild(e2, exclude_configs);
}
+
+ this->FinishWritingSource(e2, toolSettings);
}
}
@@ -2372,6 +2356,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)
{
@@ -3547,8 +3557,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();
@@ -4214,7 +4222,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();
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 55c5444..a5ce5e5 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 327c1c7..b8297ce 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/cmake.cxx b/Source/cmake.cxx
index 73f5ad5..7cafaee 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__
@@ -604,9 +605,8 @@ void cmake::ProcessCacheArg(const std::string& var, const std::string& value,
}
}
- 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 ||
@@ -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;
@@ -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
@@ -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);
@@ -2037,19 +2036,17 @@ 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);
}
@@ -2068,9 +2065,9 @@ 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 =
@@ -2086,8 +2083,7 @@ 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);
}
@@ -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, cmProp value,
const char* helpString, int type)
{
this->State->AddCacheEntry(key, value, helpString,
@@ -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(
@@ -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, cmProp value)
+{
+ this->State->SetGlobalProperty(prop, value);
+}
void cmake::AppendProperty(const std::string& prop, const std::string& value,
bool asString)
@@ -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 5a2a88f..7408044 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -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();
@@ -331,6 +332,18 @@ public:
cmProp 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 ? cmProp(std::string(value)) : cmProp(nullptr),
+ helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, const std::string& value,
+ const char* helpString, int type)
+ {
+ this->AddCacheEntry(key, cmProp(value), helpString, type);
+ }
+ void AddCacheEntry(const std::string& key, cmProp 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,6 +408,11 @@ public:
//! Set/Get a property of this target file
void SetProperty(const std::string& prop, const char* value);
+ void SetProperty(const std::string& prop, cmProp value);
+ void SetProperty(const std::string& prop, const std::string& value)
+ {
+ this->SetProperty(prop, cmProp(value));
+ }
void AppendProperty(const std::string& prop, const std::string& value,
bool asString = false);
cmProp GetProperty(const std::string& prop);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 1f4c0b8..1e0f497 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -385,18 +385,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.
diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in
index ed46d5c..16efaef 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 12f9139..f2bf85f 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 f610a70..930d84c 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 06a22dc..a847462 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 f85ef42..0a767a8 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 39a19cb..6ccc7a7 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/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 341aba6..da6b670 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
@@ -1442,6 +1449,7 @@ if(BUILD_TESTING)
GIF
Git
GLEW
+ GLUT
GnuTLS
GSL
GTK2
@@ -1543,6 +1551,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 +1650,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 52959e6..9e0b891 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 64a8ef6..5d6320b 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 8bfcf26..31a2560 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 28ee094..cf0d314 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 be5ccac..669c412 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 b01b9d7..0000000
--- 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 bc32450..0000000
--- 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 565d52e..0000000
--- 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 73e43a8..0000000
--- 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 7781ded..7c6f76a 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 2b18d24..17009bd 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,37 @@ 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_MODIFICATION
+ # 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"
+
+ # 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"
+
+ # 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"
+)
diff --git a/Tests/Environment/check_mod.cmake b/Tests/Environment/check_mod.cmake
new file mode 100644
index 0000000..16d02f2
--- /dev/null
+++ b/Tests/Environment/check_mod.cmake
@@ -0,0 +1,55 @@
+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_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(expected_vars
+ DIRECT
+ STRING_MANIP
+ PATH_MANIP
+ CMAKE_LIST_MANIP)
+
+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/FindGLUT/CMakeLists.txt b/Tests/FindGLUT/CMakeLists.txt
new file mode 100644
index 0000000..e75ec40
--- /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 0000000..0f4e536
--- /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 0000000..1c8569c
--- /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/FindMatlab/targets_checks/CMakeLists.txt b/Tests/FindMatlab/targets_checks/CMakeLists.txt
new file mode 100644
index 0000000..4af7cc3
--- /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 d4c19c7..4c488e6 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -2,17 +2,25 @@ 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 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 dee39c8..a746a68 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 a13f08f..3da308d 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 1dbe819..53759b1 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 a670c2a..3daf69e 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 70dfa01..5d58633 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 0000000..96c83a0
--- /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 0000000..a4316eb
--- /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 0000000..826e61e
--- /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 0000000..46c8fa1
--- /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 0000000..7cd32cc
--- /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 0000000..0fe72c9
--- /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 0000000..bd82d2e
--- /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 0000000..fe1cd85
--- /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 0000000..b3d9cb2
--- /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 0000000..0fe72c9
--- /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 0000000..550b2b4
--- /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 0000000..2820d5d
--- /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 0000000..e397c02
--- /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 0000000..89f3755
--- /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 0000000..0fe72c9
--- /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 0000000..245f9d4
--- /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 0000000..c405056
--- /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 0000000..7580c77
--- /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 0000000..45a177a
--- /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 0000000..5056814
--- /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 0000000..cd2c932
--- /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 0000000..60189e2
--- /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 0000000..ec12004
--- /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 0000000..ae4d25c
--- /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 0000000..aacbb96
--- /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 0000000..aacbb96
--- /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 0000000..16a481b
--- /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 0000000..eac9782
--- /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/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt b/Tests/RunCMake/CMAKE_MSVCIDE_RUN_PATH/CMakeLists.txt
new file mode 100644
index 0000000..bbc08e6
--- /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 0000000..f0f2efc
--- /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 0000000..63d6068
--- /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 0000000..a424ff2
--- /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 0000000..9037d02
--- /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 15b56a1..15b56a1 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 0000000..5a2b018
--- /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 0000000..b16e84b
--- /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 0000000..d89dbd3
--- /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 0000000..00d440d
--- /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 0000000..15b56a1
--- /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 0000000..e92c1e6
--- /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 0000000..15b56a1
--- /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 8342a01..81df003 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 e1045f2..61e046f 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 0000000..15b56a1
--- /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 0000000..6db2128
--- /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 86cb849..eb2c2d9 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -349,6 +349,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 +375,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-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 +557,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 746ff8b..7997c78 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 cf4aa51..b3e6485 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 9ff1f8a..e9cebbf 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/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
index d1a3a5f..f859215 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 fbdda9c..13af097 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 15c5892..3c922d2 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 0000000..e69de29
--- /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 0000000..202ef80
--- /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 0000000..e69de29
--- /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 0000000..03b92a7
--- /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 0000000..e5e6d04
--- /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 0000000..4a26732
--- /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 0000000..f21666f
--- /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 0000000..bfec18f
--- /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 0000000..8c9b63a
--- /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 0000000..7800a4f
--- /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 0000000..fcbbaea
--- /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 c58b1d0..cea5b1b 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)
@@ -898,3 +918,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/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_GET_MATCHING_ARGN.cmake
new file mode 100644
index 0000000..e49ff22
--- /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 0000000..6615d80
--- /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 0000000..9f654b5
--- /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 78ccd96..f36d1eb 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 b038370..c91713b 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 56bba30..4021bf7 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 0000000..cae3679
--- /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-test3-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-test3-stdout.txt
new file mode 100644
index 0000000..cf08267
--- /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 0000000..4a9d75b
--- /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 8efd117..221d6ad 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/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
index 530c8ab..c5c5925 100644
--- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake
@@ -40,6 +40,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
diff --git a/Tests/RunCMake/GoogleTest/fake_gtest.cpp b/Tests/RunCMake/GoogleTest/fake_gtest.cpp
index 1956c37..b2a5cb4 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/PrecompileHeaders/PchIncludedAllLanguages.cmake b/Tests/RunCMake/PrecompileHeaders/PchIncludedAllLanguages.cmake
new file mode 100644
index 0000000..a455410
--- /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 0000000..b4fdb71
--- /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 8cc59d2..ca5b52e 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 0000000..96fce69
--- /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 0000000..bf4d95d
--- /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 81b6d9e..20672d1 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/UseSWIG/CMP0086-OLD-stderr.txt b/Tests/RunCMake/UseSWIG/CMP0086-OLD-stderr.txt
new file mode 100644
index 0000000..fca7a73
--- /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/VsDpiAwareBadParam-stderr.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt
index 95fc5ca..39415af 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 0f8b26c..13cc8e2 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 a4b321b..3a046f1 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 f4fe07f..54375d5 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 e4ea55d..23fd49d 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 79d8d77..c76226f 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 57c79ea..732f04c 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 4c78199..f83b1bf 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 64e2f95..8c7b06a 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 e94d084..f3a6918 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 0000000..50838c3
--- /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 0000000..ad873eb
--- /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 0000000..08d8da8
--- /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 0000000..d00491f
--- /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 0000000..ed995e6
--- /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 1655eb4..1655eb4 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 0000000..d00491f
--- /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 0000000..b78c927
--- /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 1f056d5..1f056d5 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 0000000..d00491f
--- /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 0000000..c3f1314
--- /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 9c5a558..9c5a558 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 0000000..0198f9b
--- /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 0000000..50dbb08
--- /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 0000000..3bc632b
--- /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 0000000..294ccc9
--- /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 0000000..4193d6f
--- /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 0000000..cbf83a9
--- /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 0000000..c7d48f0
--- /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 0000000..11ae71f
--- /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 0000000..7fc26d8
--- /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 0000000..944c9b4
--- /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 0000000..f583deb
--- /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 a3c2b05..f22a0ae 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 0000000..eebe0d4
--- /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 1c3156d..f24aa2b 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 0000000..189013f
--- /dev/null
+++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake
@@ -0,0 +1,17 @@
+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)
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 0000000..d1a18da
--- /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 0000000..7fc26d8
--- /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 0000000..f228f22
--- /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 0000000..db6f487
--- /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 0000000..d9a0aca
--- /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 0000000..66c33b5
--- /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 0000000..78acea2
--- /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 0000000..acaf47e
--- /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 0000000..660aa1c
--- /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/ctest_environment/CMakeLists.txt.in b/Tests/RunCMake/ctest_environment/CMakeLists.txt.in
new file mode 100644
index 0000000..c9c4a64
--- /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 0000000..b57e2de
--- /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 0000000..5b56d6f
--- /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 0000000..d6ca4b2
--- /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 0000000..b57e2de
--- /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 0000000..3ba6ba7
--- /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 0000000..601dd8b
--- /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 0000000..b57e2de
--- /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 0000000..20bc9a5
--- /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 0000000..18448cf
--- /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 0000000..3447779
--- /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 0000000..ca23c83
--- /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 0000000..9d2a059
--- /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 0000000..e1fc77a
--- /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 0000000..b3473bf
--- /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 6e0a91c..cb8f696 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 5f9b32d..de81049 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 0000000..eaa50d1
--- /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 0095db0..7e0928d 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-RPATH/RunCMakeTest.cmake b/Tests/RunCMake/file-RPATH/RunCMakeTest.cmake
index eb7b497..1ca2e75 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/find_library/FromScriptMode-stderr-darwin.txt b/Tests/RunCMake/find_library/FromScriptMode-stderr-darwin.txt
new file mode 100644
index 0000000..185720b
--- /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 0000000..501ec0f
--- /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 0000000..046f680
--- /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 0000000..4d3c699
--- /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 e297173..ad02c82 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 0000000..0db83aa
--- /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 0000000..d00491f
--- /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 0000000..f6c0b44
--- /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 0000000..5935316
--- /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 0000000..d00491f
--- /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 0000000..b4fdd98
--- /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 0000000..04fece7
--- /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 3ba04c8..b20a889 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 0000000..634d988
--- /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 0000000..7142cfc
--- /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 0000000..d00491f
--- /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 0000000..6e8ac80
--- /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 0000000..a3ef2b8
--- /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 f54edf7..6baa840 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 0000000..d00491f
--- /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 0000000..770ccb8f
--- /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 0000000..c51c755
--- /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 0000000..5233ebc
--- /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 cd4dcb3..d54777b 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 cba258d..7fd6d72 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 5b4761c..cf4c540 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 7da80ac..bb9b991 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 0000000..d00491f
--- /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 0000000..9d4132c
--- /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 0000000..7a12701
--- /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 f1b2f32..c3f9e03 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
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index 0ccb721..69b4e2f 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 f1bdcc4..8c55c85 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 b2e14d5..25a063a 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/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 34ff4de..abd54f6 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_0"
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 0000000..1a065ba
--- /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 f8fe544..5ed00e7 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 3db89ff..3a24e2b 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/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index 32efd48..a71dfcd 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)
diff --git a/Utilities/cmThirdPartyChecks.cmake b/Utilities/cmThirdPartyChecks.cmake
index bab3046..7e38df9 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 2fcce1b..e418146 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 bbd4632..7fda7ac 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 c393557..dd653da 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 16ef037..9eef01a 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 55a6a39..7b50b7c 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 a8d5449..6c20917 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -30,12 +30,12 @@
/* 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.0"
/* 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_MINOR 79
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -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 0x074f00
/*
* 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 7343cb6..1d70880 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 4ab77fd..36acc3a 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 7827847..763a4aa 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 36f68cb..149172a 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 81f589e..26635cd 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 d60ed78..d63defe 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 5453c00..f5ba8ff 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 d9317f3..d61b037 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 941623f..b7531f7 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 460bbb1..0ffe08e 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 1d5067b..842fd7f 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 4fdc672..de03550 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 b6f107e..ecde74b 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 acaaa1c..5810dad 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 16418be..e9d2a8c 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 89d4ec8..749b44e 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 9af79fd..5a3bc3c 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 f7fb7c0..24bdb30 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 a4d1059..4a24887 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 2d13a40..554dcc1 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 22d0a06..38018d2 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 625b057..5d53b8f 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 36f8cd5..de0c902 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 b3584d1..70e96e0 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 530b7c7..2aca938 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 769f06a..ac7a000 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 425b0af..cad584f 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 b25de1d..f7d99ce 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 49dbab3..cf267a7 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 e0e3cfc..117caa2 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 d178976..67a688a 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 d0754af..1fd7910 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 9791d86..c2d5f08 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 550b43a..c00c274 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 ef166f1..853c7df 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -138,6 +138,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++;
@@ -521,7 +526,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/http.c b/Utilities/cmcurl/lib/http.c
index 628dd73..d5c36dd 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;
+ int digit4 = -1; /* should remain untouched to be good */
nc = sscanf(HEADER1,
- " HTTP/%1d.%1d%c%3d",
+ " HTTP/%1d.%1d%c%3d%1d",
&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,6 +4248,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
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 is not -1 */
+ else if(digit4 != -1) {
+ failf(data, "Unsupported response code in HTTP response");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
if((nc == 4) && (' ' == separator)) {
httpversion += 10 * httpversion_major;
switch(httpversion) {
@@ -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 2a3834a..e4ab466 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 f194c18..a3de607 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,22 @@ 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;
+
+ httpc->inbuflen = 0;
+ httpc->nread_inbuf = 0;
+
+ httpc->pause_stream_id = 0;
+ httpc->drain_total = 0;
+
+ 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,25 +2246,13 @@ 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;
-
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
-
- httpc->pause_stream_id = 0;
- httpc->drain_total = 0;
+ infof(data, "Using HTTP2, server supports multiplexing");
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 21e2c08..d6986d9 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 a04b46a..02663ab 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 049b232..34bb5a8 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 68cce1b..5f764dc 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 e200fdb..627a11c 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 a3a62c1..58489ab 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 f5a4cb0..cdf8de4 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 d85bcc3..6163899 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 4c3e9e4..b5f9b80 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 c8c4b66..659947d 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 ed16423..1d9e44c 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 c651ddf..e7a428f 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 7a24fd8..983ed97 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 5292026..7a1aec5 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 d88fa73..fcd40b4 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 1b3e261..8509781 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,7 +1042,12 @@ 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;
@@ -1096,6 +1100,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 +1183,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 +1192,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 +1547,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 +1729,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 +1743,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 +1758,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 +1819,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 +1874,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 +2306,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 +2445,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 +3381,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 +3428,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 +3436,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 96b8474..2e4a6ff 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 13610bb..0a4ae2c 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 932cf89..3b77ae9 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 0b8bc34..fb5e743 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 4811739..84c7f51 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 9b6ea64..d3f3de6 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 4bcd615..f5ef6bd 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 947f13e..b030359 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 951fedb..8f2c1ba 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 007d5c5..30fefb9 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 1e9cb7d..da11ade 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 4db6487..19da1e7 100644
--- a/Utilities/cmcurl/lib/select.h
+++ b/Utilities/cmcurl/lib/select.h
@@ -106,7 +106,11 @@ int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
} \
} while(0)
#else
+#ifdef HAVE_POLL_FINE
+#define VALID_SOCK(s) ((s) >= 0) /* FD_SETSIZE is irrelevant for poll */
+#else
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
+#endif
#define VERIFY_SOCK(x) do { \
if(!VALID_SOCK(x)) { \
SET_SOCKERRNO(EINVAL); \
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index e41bb80..14ca84b 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 fb8b86d..08827d1 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 c34f97e..a2e7e41 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 39facb2..fd49cf6 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 feffc05..02ddaca 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 2c580ad..409d2ad 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 5cde4a4..db4c808 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 10b942a..34bfa37 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 813c6be..cb225b9 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 9af47ea..85cf33b 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 0936956..8c8a6f2 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 5298a0d..431ff1c 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)";
@@ -731,6 +731,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
max = buflen - 1;
*buf = '\0';
+ /* !checksrc! disable STRERROR 2 */
#if defined(WIN32) || defined(_WIN32_WCE)
#if defined(WIN32)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index fdd137f..a81bb81 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 11150af..aae997d 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 bca4e54..3e650b5 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");
}
}
}
@@ -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 1ee38af..37b6c0e 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 6483208..7f03862 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 fb905c3..6ffd976 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 2602ffd..94f8f8c 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 b43982b..67d43bd 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 e110644..c652fd7 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 47e5357..0aa3f1c 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 1b1a176..3e39dad 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 120925f..8e8932b 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 4aa1ba9..68bb17d 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 ec5b000..47a7c0b 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 b67b9a4..c84ef85 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 7f07675..9fcfe81 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 cbede45..5014530 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 b62d884..f757760 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 d146d15..3e317e8 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 8a6345b..a772f1f 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 505b078..7972081 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 9f3266a..4b1e2ec 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 7f72971..e87649e 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 ca95376..e451f6a 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 ecde5c4..1b145d8 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 3a0be0f..780d13e 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 473f517..751755c 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 bf8600d..3db9184 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 1582b1e..cf65789 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 ebd7abc..87f4b02 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 d5247f9..2ac97ce 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 3286a9e..722a937 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 25d47b8..1b283d0 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 edd375e..1e6ed5f 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 65f4f77..e5bbe1f 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 7f93e7a..beaa83d 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 60e27e3..16fbb89 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 c0764c4..15c8156 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 281c972..1bdaead 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 326e32d..3b51eee 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/.gitattributes b/Utilities/cmelf/.gitattributes
new file mode 100644
index 0000000..562b12e
--- /dev/null
+++ b/Utilities/cmelf/.gitattributes
@@ -0,0 +1 @@
+* -whitespace
diff --git a/Utilities/cmelf/elf32.h b/Utilities/cmelf/elf32.h
new file mode 100644
index 0000000..20d2ec2
--- /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 0000000..6efe147
--- /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 0000000..395c45b
--- /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 9562436..a685da1 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 f64913f..415c463 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 2cc8462..f03b746 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 70bbe19..affe33a 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 5964672..5c776a1 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 365abb3..6b99b4d 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 667246a..7ad0be6 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 7b90c5a..952d423 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 d953961..5b9783d 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 d3ae62b..cc6b78c 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 8291cc6..e6caf40 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 4316178..2d7b7d9 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 f271e57..d59b7d9 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 5243bfe..d6128b8 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 fc86505..8bf02db 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 79452ff..ba65470 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 14bbefa..1b97235 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 fc8529a..bc5a43f 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 f38601f..9bd2667 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 78be3ab..205791c 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 574e087..a1f0b87 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 952e20d..ead7e36 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 288ce23..1f40072 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 8ab2b09..d4bca90 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 64a2055..16b6d16 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 34c58ac..410df01 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 15312ee..9b3bd66 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 a15e98c..ca7a4bd 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 0053faa..21e89d2 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 2b9a084..cf4deb2 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 aa5c8e0..29a53f7 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 4029395..cc3f778 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 4a933b2..c59f051 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 cf821b5..f0b1ab9 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 2a8cec8..9c9cf38 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 52fec7b..2898206 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 1ba5fcb..4f5c351 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 86635e2..561289b 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 1d3e49d..796dcdc 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 0000000..94c4af6
--- /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 b8bf128..bf5b6f2 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 e1ec60e..c4e8ec7 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 034353d..89e96f1 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 58644ba..57547d4 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 c641eb9..53fb6cc 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 332944a..93ba295 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 61f2330..6dca350 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 d3a1c1b..3131955 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 c63d46f..96d8101 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 72977b8..2732996 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 9489e51..2e60cf7 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 4d71f98..6314c68 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 c77dcf5..7460ded 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 27e1ad6..49d7d30 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 10dca73..83586b5 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 98a55fb..8d70f51 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 a4bc1d9..c096e72 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 d567ac9..00df8da 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 f67b025..6d71628 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 c4be9b0..2551ebe 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 77e36c4..0c60017 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 0129d10..29bffe4 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 d5c426c..b8d491f 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 f6b1412..bf5b55a 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 66e0dfe..9ceefb1 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 ea6ae0a..a8a0b81 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 27cba03..155fdd7 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 12de080..7dbe7b9 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 69af814..7f2e6ac 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 729f9c7..e066733 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 172fda6..f0f3980 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 5db414f..68e3fe3 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 aa41e9a..619b771 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 3b0ffb3..1e35375 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 b0cd215..66a1f84 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 cffe571..d4a52e3 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 f16fd34..a484618 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 1a2886f..a91f0c5 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 908e7cd..2bf290c 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 02dbd4b..ac255c4 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 ad271fe..8d11179 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/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index 04718db..aada889 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/bootstrap b/bootstrap
index dc5ed0b..d0329fb 100755
--- a/bootstrap
+++ b/bootstrap
@@ -324,6 +324,7 @@ CMAKE_CXX_SOURCES="\
cmDefinePropertyCommand \
cmDefinitions \
cmDocumentationFormatter \
+ cmELF \
cmEnableLanguageCommand \
cmEnableTestingCommand \
cmExecProgramCommand \
@@ -425,6 +426,7 @@ CMAKE_CXX_SOURCES="\
cmPolicies \
cmProcessOutput \
cmProjectCommand \
+ cmProperty \
cmPropertyDefinition \
cmPropertyMap \
cmGccDepfileLexerHelper \